区块链(一)

实践——一个极简的区块链

区块链: 区块的记录构成的不可变的,有序的链结构(通过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;
    }
    
}

这些类还原了一个较简单的区块链,完成了块生成,块链完整校验,散列计算(计算哈希值),工作量计算。

多谢诸位愿聆听区区之见解,若有差错,望不吝指教。

posted on 2018-02-27 21:06  ~(~ ̄▽ ̄)~  阅读(219)  评论(0)    收藏  举报

导航