区块链(一)
实践——一个极简的区块链
区块链: 区块的记录构成的不可变的,有序的链结构(通过Hash值链接)
原文:https://juejin.im/post/5a8ed1d75188257a836c4218
1.算法SHA256将传入参数转换成哈希值返回
public class ShaUtils { // SHA256加密 public static String applySha256(String input){ try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); //对输入使用 sha256 算法 byte[] hash = digest.digest(input.getBytes("UTF-8")); StringBuffer hexString = new StringBuffer(); // 它会包含16进制的 hash 值 for (int i = 0; i < hash.length; i++) { String hex = Integer.toHexString(0xff & hash[i]); if(hex.length() == 1) hexString.append('0'); hexString.append(hex); } return hexString.toString(); } catch(Exception e) { throw new RuntimeException(e); } } }
2.创建Block(嗯。。算个实例类吧)
所需变量:
1.index:更新index可以不断通过calculateHash方法生成所需哈希值(可有可无,可用timeStamp代替)
2.hash:用SHA256算法生成的哈希值
3.prevHash:前一个块的哈希值
4.data:数据(自定义)
5.timeStamp:当前时间的时间戳
calculateHash方法:
获取上方的prevHash,data,timeStamp, index变量,通过之前定义的applySha256方法将其转化成哈希值
diffBlock方法(这个至关重要关系到挖矿判定):
difficulty:你希望hash值开头的0的个数(自定义,与挖矿速率有关)
target:difficulty * "0"
不断更新index与timeStamp产生新的哈希值直到对应的哈希值产生,将其返回
1 public class Block { 2 3 private int index; // 更新index可以不断通过calculaeHash方法生成所需的哈希值 4 private String hash; // Hash 5 private String prevHash; // 前一个块的Hash 6 private String data; // 数据 7 private Long timeStamp; // 时间戳 8 9 // 返回SHA256加密数据 10 public String calculateHash () { 11 StringBuffer sb = new StringBuffer().append(prevHash).append(data).append(timeStamp).append(index); 12 String applyStr = ShaUtils.applySha256(sb.toString()); 13 return applyStr; 14 } 15 16 // 构造 17 public Block (String prevHash, String data) { 18 this.prevHash = prevHash; 19 this.data = data; 20 this.timeStamp = new Date().getTime(); 21 this.hash = calculateHash(); // 计算Hash值 22 } 23 24 // 验证hashcash,hash开头的0的个数 25 public void diffBlock (int difficulty) { 26 String target = new String(new char[difficulty]).replace('\0', '0'); //创建一个用 difficulty * "0" 组成的字符串 27 // 截取hash前difficulty位,判断是否与target一致 28 while(!hash.substring( 0, difficulty).equals(target)) { 29 index ++; 30 hash = calculateHash(); 31 } 32 System.out.println("Block Mined!!! : " + hash); 33 } 34 }
3. 测试类
全局变量:
blockChain:区块链
complexity:挖矿复杂度(也就是diffBlock方法的参数)
isChainValid方法:块检验
1.循环整个区块链,从1开始,0为创世块(数据固定)
2. 判断一:判断链中hash与计算hash是否一致
3. 判断二:判断当前块中prevHash是否与前一块中的hash是否一致
main方法测试自行观看(最后一步通过GSON库将区块链转换成JSON)
public class BlockChain { // blockChain private static List<Block> blockChain = new ArrayList<Block> (); private static int complexity = 10; // 测试block public static void main(String[]args) { Block b1 = new Block ("0", "FirstHash"); System.out.println(b1.getHash()); Block b2 = new Block (b1.getHash(), "SecondHash"); System.out.println(b2.getHash()); Block b3 = new Block (b2.getHash(), "ThirdHash"); System.out.println(b3.getHash()); // 将区块加入链中 blockChain.add(new Block("0", "FirstHash")); blockChain.get(0).diffBlock(complexity);blockChain.add(new Block(blockChain.get(blockChain.size() - 1).getHash(), "SecondHash")); blockChain.get(1).diffBlock(complexity); blockChain.add(new Block(blockChain.get(blockChain.size() - 1).getHash(), "ThirdHash")); blockChain.get(2).diffBlock(complexity); // 验证 System.out.println("isChainValid = " + isChainValid()); // 链转换为JSON String blockStr = new GsonBuilder().setPrettyPrinting().create().toJson(blockChain); System.out.println("blockChain Json = " + blockStr); } // 验证链完整性 public static boolean isChainValid () { Block currentBlock; Block previousBlock; // 从1开始,0为创世硬编码 for (int i=1; i < blockChain.size(); i++) { currentBlock = blockChain.get(i); previousBlock = blockChain.get(i - 1); // 判断计算的Hash与链中Hash是否一致 if (!currentBlock.getHash().equals(currentBlock.calculateHash())) { System.out.println("Inconsistencies in hash = " + currentBlock.getHash()); return false; } // 判断prevHash与前一块的Hash是否一致 if (!currentBlock.getPrevHash().equals(previousBlock.getHash())) { System.out.println("Hash is not equal to Previous = " + currentBlock.getHash()); } } return true; } }
这些类还原了一个较简单的区块链,完成了块生成,块链完整校验,散列计算(计算哈希值),工作量计算。
多谢诸位愿聆听区区之见解,若有差错,望不吝指教。
浙公网安备 33010602011771号