简化模拟:
0.假设挖矿难度为整数d(d>0)
1.随机生成一个整数x
2.对整数x进行摘要计算hash(x),得到s,即s=hash(x)
3.对s前导字符串判定:如为d个'0',则矿已挖到,结束;否则跳到步骤1.
一句话:不断随机生成整数,直到对生成的整数被进行摘要计算得到的字符串以某个数目的0开头为止。
摘要算法选用sha256
代码实现:
1 package cn.ubingo.block_chain; 2 3 import java.util.Collections; 4 import java.util.Date; 5 import java.util.Random; 6 7 public class Demo { 8 static Random r = new Random(); 9 10 public static void main(String[] args) { 11 12 int dificulty = 3; 13 String zeros = String.join("", Collections.nCopies(dificulty, "0")); 14 System.out.println(zeros); 15 16 Date start = new Date(); 17 long times = 0; 18 while (true) { 19 String sha = Sha.getSHA256StrJava(r.nextInt() + ""); 20 // System.out.println(sha); 21 times++; 22 if (sha.startsWith(zeros)) 23 break; 24 } 25 Date end = new Date(); 26 long use = end.getTime() - start.getTime(); 27 28 System.out.println(times + " in " + use + "ms with dificulty " + dificulty); 29 } 30 31 }
输出结果:
000
4973 in 106ms with dificulty 3
耗时计算:
让难度从1递增,每个难度挖10次矿,取耗时最久的那次作为参考。
package cn.ubingo.block_chain; import java.util.Collections; import java.util.Date; import java.util.Random; public class App { static Random r = new Random(); public static void main(String[] args) { int dificulty = 0; while (true) { dificulty++; String zeros = String.join("", Collections.nCopies(dificulty, "0")); System.out.println(zeros); long maxUse = 0; long maxTimes = 0; for (int i = 0; i < 10; i++) { Date start = new Date(); long times = 0; while (true) { String sha = Sha.getSHA256StrJava(r.nextInt() + ""); //System.out.println(sha); times++; if (sha.startsWith(zeros)) break; } Date end = new Date(); long use = end.getTime() - start.getTime(); if (use > maxUse) { maxUse = use; maxTimes = times; } } System.out.println(maxTimes + " in " + maxUse + "ms with dificulty " + dificulty); } } }
输出结果(代码还在跑):
0
19 in 32ms with dificulty 1
00
366 in 11ms with dificulty 2
000
11377 in 73ms with dificulty 3
0000
153888 in 377ms with dificulty 4
00000
3160837 in 4568ms with dificulty 5
000000
55559940 in 81454ms with dificulty 6
0000000
637485941 in 977748ms with dificulty 7
00000000
8540898666 in 12283075ms with dificulty 8
000000000
===========================================================
从上面结果可以看出,当难度为8时,一个人挖,耗时204分钟(12283075ms)左右。
由于挖矿算法具有的随机性,如要求在10分钟内挖到矿,需要204/10=20个同等算力的矿工同时挖。
如果难度为72(比特币当前的难度),可想而知需要的矿工数量得是什么级别。
由于挖矿算法具有的随机性,谁的算力强,谁的矿工多,谁挖到矿的几率就大,谁就能发大财。(所以矿机和矿场登场了)
===========================================================
代码中用到的工具类如下(网上找的):
package cn.ubingo.block_chain; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Sha { /** * 利用java原生的摘要实现SHA256摘要计算 * @param content 原文 * @return */ public static String getSHA256StrJava(String content){ MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(content.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encodeStr; } /** * 将byte转为16进制 * @param bytes * @return */ private static String byte2Hex(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i=0;i<bytes.length;i++){ temp = Integer.toHexString(bytes[i] & 0xFF); if (temp.length()==1){ //1得到一位的进行补0操作 stringBuffer.append("0"); } stringBuffer.append(temp); } return stringBuffer.toString(); } }