参考网站:
https://jeiwan.cc/posts/building-blockchain-in-go-part-1/
https://github.com/liuchengxu/blockchain-tutorial/blob/master/content/part-1/basic-prototype.md#%E5%8C%BA%E5%9D%97%E9%93%BE
前言:
区块链是 21 世纪最具革命性的技术之一,它仍然处于不断成长的阶段,而且还有很多潜力尚未显现。 本质上,区块链只是一个分布式数据库而已。 不过,使它独一无二的是,区块链是一个公开的数据库,而不是一个私人数据库,也就是说,每个使用它的人都有一个完整或部分的副本。 只有经过其他“数据库管理员”的同意,才能向数据库中添加新的记录。 此外,也正是由于区块链,才使得加密货币和智能合约成为现实。
区块:
首先从 “区块” 谈起。在区块链中,真正存储有效信息的是区块(block)。而在比特币中,真正有价值的信息就是交易(transaction)。实际上,交易信息是所有加密货币的价值所在。除此以外,区块还包含了一些技术实现的相关信息,比如版本,当前时间戳和前一个区块的哈希。
不过,我们要实现的是一个简化版的区块链,而不是一个像比特币技术规范所描述那样成熟完备的区块链。所以在我们目前的实现中,区块仅包含了部分关键信息,它的数据结构如下:
@Getter public class Block { private long timestamp; // 区块创建的时间 private byte[] data; //区块储存的有效信息 private byte[] prevBlockHash; //上一个区块的哈希值 private byte[] hash; //当前块的Hash块 }
在比特币中,有两部分数据,一种是Header数据(timestamp、preBlockHash、hash等)和交易数据 (data),这里简化模型,将两部分数据合并在一起。
下面创建Block的构造函数和hash处理函数,我们这里将timestamp、preBlockHash和data拼接起来使用SHA-256计算得到一个哈希。
public void setHash() { byte[] time = (timestamp + "").getBytes(); byte[] target = new byte[time.length + data.length + prevBlockHash.length]; int index = 0; System.arraycopy(time, 0, target, index, time.length); index += time.length; System.arraycopy(prevBlockHash, 0, target, index, prevBlockHash.length); index += prevBlockHash.length; System.arraycopy(data, 0, target, index, data.length); hash = SHA256Util.getSHA256Bytes(target); } public Block(byte[] data, byte[] prevBlockHash) { if (data == null || prevBlockHash == null || data.length == 0) { throw new RuntimeException("error block!"); } this.data = data; this.prevBlockHash = prevBlockHash; this.timestamp = new Date().getTime(); setHash(); }
区块链:
有了区块,下面让我们来实现区块链。本质上,区块链就是一个有着特定结构的数据库,是一个有序,每一个块都连接到前一个块的链表。也就是说,区块按照插入的顺序进行存储,每个块都与前一个块相连。这样的结构,能够让我们快速地获取链上的最新块,并且高效地通过哈希来检索一个块。
public class BlockChain { //这里暂时只用一个List就OK private Listblocks; public BlockChain() { blocks = new ArrayList<>(); //添加初始块 blocks.add(new Block("Genesis Block".getBytes(), new byte[]{})); } public void addBlock(byte[] data) { if (data == null || data.length == 0) { throw new RuntimeException("data can't be empty"); } Block preBlock = blocks.get(blocks.size() - 1); blocks.add(new Block(data, preBlock.getHash())); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (Block block : blocks) { sb.append("================\n"); sb.append("data : ").append(new String(block.getData())).append("\n"); sb.append("preHash : ").append(ByteUtils.byte2Hex(block.getPrevBlockHash())).append("\n"); sb.append("hash : ").append(ByteUtils.byte2Hex(block.getHash())).append("\n"); } sb.append("length : ").append(blocks.size()); return sb.toString(); } }
测试效果
public static void main(String[] args) { BlockChain blockChain = new BlockChain(); blockChain.addBlock("Block1".getBytes()); blockChain.addBlock("Block2".getBytes()); System.out.println(blockChain.toString()); }
结果 ================ data : Genesis Block preHash : hash : cde7c1538c6b384fa7af18e6ce6f7cde3440028c5d599ffd8bb61121e6b46681 ================ data : Block1 preHash : cde7c1538c6b384fa7af18e6ce6f7cde3440028c5d599ffd8bb61121e6b46681 hash : 074d9d9f9bba1d6d2471e2f97e95564841107368f773112df5e1d05d7381ee58 ================ data : Block2 preHash : 074d9d9f9bba1d6d2471e2f97e95564841107368f773112df5e1d05d7381ee58 hash : c6079e03785a5093ce0caa4116e78ada790d227425337f65668d6ed8fb9a3baa length : 3
总结:
我们创建了一个非常简单的区块链原型:它仅仅是一个数组构成的一系列区块,每个块都与前一个块相关联。真实的区块链要比这复杂得多。在我们的区块链中,加入新的块非常简单,也很快,但是在真实的区块链中,加入新的块需要很多工作:你必须要经过十分繁重的计算(这个机制叫做工作量证明),来获得添加一个新块的权力。并且,区块链是一个分布式数据库,并且没有单一决策者。因此,要加入一个新块,必须要被网络的其他参与者确认和同意(这个机制叫做共识(consensus))。还有一点,我们的区块链还没有任何的交易!