├── .gitignore ├── pom.xml ├── src └── main │ └── java │ ├── Demo.java │ ├── Block.java │ ├── StringUtil.java │ └── ImportChain.java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | out 9 | gen 10 | .idea/ 11 | blockchain-samples.iml 12 | target/ 13 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.importsource 8 | blockchain-samples 9 | 1.0-SNAPSHOT 10 | 11 | 12 | com.google.code.gson 13 | gson 14 | 2.8.2 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/Demo.java: -------------------------------------------------------------------------------- 1 | import com.google.gson.GsonBuilder; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * @author hezhuofan 7 | */ 8 | public class Demo { 9 | public static ArrayList blockchain = new ArrayList(); 10 | 11 | public static void main(String[] args) { 12 | //add our blocks to the blockchain ArrayList: 13 | blockchain.add(new Block("Hi im the first block", "0")); 14 | blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash)); 15 | blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash)); 16 | 17 | String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain); 18 | System.out.println(blockchainJson); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 自己动手写区块链系列 2 | 3 | 关注此公众号了解更多相关内容 4 | 5 | 6 | 7 | ### 1.0.区块链基本的了解 8 | 9 | 参阅:https://www.zhihu.com/question/20792042 10 | 11 | ### 1.1.自己动手写区块链-创建一个基本的区块链雏形(Java版) 12 | 13 | github地址:https://github.com/importsource/blockchain-samples 14 | 15 | 开发指南:https://mp.weixin.qq.com/s?__biz=MzA5MzQ2NTY0OA==&mid=2650797410&idx=1&sn=c16d1b0064768479a05dc65cf2b542d3&chksm=8856283dbf21a12be25300c012dc344199320f54a13b54d595c4db899d74ede95cb06d7e784c#rd 16 | 17 | 18 | ### 1.2.自己动手写区块链-发起一笔交易(Java版) 19 | 20 | github地址:https://github.com/importsource/blockchain-samples-transaction 21 | 22 | 开发指南:https://mp.weixin.qq.com/s?__biz=MzA5MzQ2NTY0OA==&mid=2650797427&idx=1&sn=ba11e0bbe90b4776b73412264856e98c&chksm=8856282cbf21a13ab4e3031d4ce1eb2ea6ce66fa6ea182f509a104f5d9258c3144f4be149886#rd 23 | 24 | ### 1.3.todo。。。 25 | -------------------------------------------------------------------------------- /src/main/java/Block.java: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | public class Block { 4 | 5 | public String hash; 6 | public String previousHash; 7 | private String data; //our data will be a simple message. 8 | private long timeStamp; //as number of milliseconds since 1/1/1970. 9 | private int nonce; 10 | 11 | //Block Constructor. 12 | public Block(String data,String previousHash ) { 13 | this.data = data; 14 | this.previousHash = previousHash; 15 | this.timeStamp = new Date().getTime(); 16 | 17 | this.hash = calculateHash(); //Making sure we do this after we set the other values. 18 | } 19 | 20 | //Calculate new hash based on blocks contents 21 | public String calculateHash() { 22 | String calculatedhash = StringUtil.applySha256( 23 | previousHash + 24 | Long.toString(timeStamp) + 25 | Integer.toString(nonce) + 26 | data 27 | ); 28 | return calculatedhash; 29 | } 30 | 31 | //Increases nonce value until hash target is reached. 32 | public void mineBlock(int difficulty) { 33 | String target = StringUtil.getDificultyString(difficulty); //Create a string with difficulty * "0" 34 | while(!hash.substring( 0, difficulty).equals(target)) { 35 | nonce ++; 36 | hash = calculateHash(); 37 | } 38 | System.out.println("Block已挖到!!! : " + hash); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/StringUtil.java: -------------------------------------------------------------------------------- 1 | import com.google.gson.GsonBuilder; 2 | 3 | import java.security.MessageDigest; 4 | 5 | public class StringUtil { 6 | 7 | //Applies Sha256 to a string and returns the result. 8 | public static String applySha256(String input){ 9 | 10 | try { 11 | MessageDigest digest = MessageDigest.getInstance("SHA-256"); 12 | 13 | //Applies sha256 to our input, 14 | byte[] hash = digest.digest(input.getBytes("UTF-8")); 15 | 16 | StringBuffer hexString = new StringBuffer(); // This will contain hash as hexidecimal 17 | for (int i = 0; i < hash.length; i++) { 18 | String hex = Integer.toHexString(0xff & hash[i]); 19 | if(hex.length() == 1) hexString.append('0'); 20 | hexString.append(hex); 21 | } 22 | return hexString.toString(); 23 | } 24 | catch(Exception e) { 25 | throw new RuntimeException(e); 26 | } 27 | } 28 | 29 | //Short hand helper to turn Object into a json string 30 | public static String getJson(Object o) { 31 | return new GsonBuilder().setPrettyPrinting().create().toJson(o); 32 | } 33 | 34 | //Returns difficulty string target, to compare to hash. eg difficulty of 5 will return "00000" 35 | public static String getDificultyString(int difficulty) { 36 | return new String(new char[difficulty]).replace('\0', '0'); 37 | } 38 | 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/ImportChain.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class ImportChain { 4 | 5 | public static ArrayList blockchain = new ArrayList(); 6 | public static int difficulty = 5; 7 | 8 | public static void main(String[] args) { 9 | //add our blocks to the blockchain ArrayList: 10 | 11 | System.out.println("正在尝试挖掘block 1... "); 12 | addBlock(new Block("Hi im the first block", "0")); 13 | 14 | System.out.println("正在尝试挖掘block 2... "); 15 | addBlock(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash)); 16 | 17 | System.out.println("正在尝试挖掘block 3... "); 18 | addBlock(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash)); 19 | 20 | System.out.println("\nBlockchain is Valid: " + isChainValid()); 21 | 22 | String blockchainJson = StringUtil.getJson(blockchain); 23 | System.out.println("\nThe block chain: "); 24 | System.out.println(blockchainJson); 25 | } 26 | 27 | public static Boolean isChainValid() { 28 | Block currentBlock; 29 | Block previousBlock; 30 | String hashTarget = new String(new char[difficulty]).replace('\0', '0'); 31 | 32 | //loop through blockchain to check hashes: 33 | for(int i=1; i < blockchain.size(); i++) { 34 | currentBlock = blockchain.get(i); 35 | previousBlock = blockchain.get(i-1); 36 | //compare registered hash and calculated hash: 37 | if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){ 38 | System.out.println("Current Hashes not equal"); 39 | return false; 40 | } 41 | //compare previous hash and registered previous hash 42 | if(!previousBlock.hash.equals(currentBlock.previousHash) ) { 43 | System.out.println("Previous Hashes not equal"); 44 | return false; 45 | } 46 | //check if hash is solved 47 | if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) { 48 | System.out.println("This block hasn't been mined"); 49 | return false; 50 | } 51 | 52 | } 53 | return true; 54 | } 55 | 56 | public static void addBlock(Block newBlock) { 57 | newBlock.mineBlock(difficulty); 58 | blockchain.add(newBlock); 59 | } 60 | } --------------------------------------------------------------------------------