博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

比特币挖矿算法简化模拟及耗时估算

Posted on 2018-08-22 10:19  fochan  阅读(1806)  评论(0编辑  收藏  举报

简化模拟

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();
    }
    
}