參考網站:
https://jeiwan.cc/posts/building-blockchain-in-go-part-1/
前言:
區塊鏈是 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 List<Block> blocks; 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))。還有一點,我們的區塊鏈還沒有任何的交易!