寫一個系列文章,由簡入深搭建一個區塊鏈網絡,也是從零開始開發一個開源項目。
不再介紹區塊鏈的基礎知識了,所以希望讀者提前了解區塊鏈的基礎知識,項目是使用Maven+JAVA開發,所以也需要讀者了解JAVA語言。本文為第一篇。
區塊
區塊屬性定義
第一步首先是區塊信息的定義,暫時不考慮那么復雜,這里只定義一些最基礎的屬性:
- 區塊號: 就是區塊的序號。
- 當前區塊哈希值: 保證區塊唯一,同時后一個區塊鏈通過保留這一屬性鏈接該區塊。
- 前一區塊哈希值: 用於鏈接上一個區塊。
- 時間戳: 記錄該區塊產出時間。
- 數據: 區塊中存儲的數據,為了簡單化,這里使用字符串代替。
目前暫時只定義這些屬性,后面開發如果需要其他屬性再進行迭代。接下來是構造方法了:
構造方法定義
構建一個新的區塊需要傳入被構建區塊的區塊號,區塊數據以及前一個區塊的哈希值。
#Block.java
@Getter # lombok工具包,加上這兩個注釋就不用寫get(),set()方法了
@Setter #工具包在下面
public class Block {
// 區塊號
public int blkNum;
// 當前區塊哈希值
public String curBlockHash;
// 前一個區塊的哈希值
public String prevBlockHash;
// 生成當前區塊的時間,用時間戳表示
public String timeStamp;
// 當前區塊中的Transaction,使用字符串簡單代替
public String data;
public Block(int blkNum,String data, String prevBlockHash){
this.blkNum = blkNum;
this.data = data;
this.prevBlockHash = prevBlockHash;
this.timeStamp = Util.getTimeStamp();
}
@Override
public String toString(){
return JSONObject.toJSONString(this);
}
}
其中涉及到獲取時間戳的getTimeStamp()
方法以及計算哈希值的getSHA256()
方法。
#Util.java
public final class Util{
public static String getSHA256(String data) {
byte[] b = {};
try{
MessageDigest md = MessageDigest.getInstance("SHA-256");
b = md.digest(data.getBytes());
}catch(NoSuchAlgorithmException e){
}
return Hex.encodeHexString(b);
}
public static String getTimeStamp(){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式
String date = df.format(new java.util.Date());
return date;
}
}
這里使用到了幾個工具包,可以在Maven的pom.xml
文件<dependencies>
標簽中添加如下字段:
#pom.xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
區塊鏈
我們需要一個區塊鏈實例,用於記錄所產出的區塊。定義的區塊鏈屬性如下:
- 區塊鏈實例: 需要靜態的(或者使用單例模式),保證只存在一個區塊鏈實例。
- 區塊集合: 定義一個集合用於保存產出的區塊。
#Blockchain.java
private static Blockchain BC;
public ArrayList<Block> block;
private Blockchain(){}
public static Blockchain getInstance(){
if(BC==null){
synchronized(Blockchain.class){
if(BC==null){
BC = new Blockchain();
BC.block = new ArrayList<Block>();
}
}
}
return BC;
}
創建第一個區塊
目前沒有其他屬性需要,接下來是定義方法。區塊鏈實例定義完成,接下來可以創建區塊鏈中的區塊了,由於創世區塊與后續區塊稍微不同,所以定義一個構建創世區塊的方法:
public Block CrtGenesisBlock(){
Block block = new Block(1,"Genesis Block","00000000000000000");
//計算區塊哈希值
String hash = Util.getSHA256(block.getBlkNum()+block.getData()+block.getPrevBlockHash()+block.getPrevBlockHash()+block.getNonce());
block.setCurBlockHash(hash);
this.block.add(block);
return this.block.get(0);
}
由於創世區塊是第一個區塊,因此不存在前一個區塊哈希值,直接定義為字符串"00000000000000000"。
添加區塊
接下來是第二個方法,創建創世區塊的后續區塊方法:
#傳入的參數為需要區塊中存儲的數據
public Block addBlock(String data){
#獲取區塊集合的大小,即獲取當前已經產出幾個區塊
int num = this.block.size();
Block block = new Block(
# 區塊號為當前區塊集合大小+1
num+1,data, this.block.get(num-1).curBlockHash);
String hash = Util.getSHA256(block.getBlkNum()+block.getData()+block.getPrevBlockHash()+block.getPrevBlockHash());
block.setCurBlockHash(hash);
#將創建的區塊添加到區塊鏈中
this.block.add(block);
return this.block.get(num);
}
OK,一個簡單的區塊鏈已經完成,測試一下:
#Test.java
public class Test {
public static void main(String[] args){
System.out.println(Blockchain.getInstance().CrtGenesisBlock().toString());
System.out.println(Blockchain.getInstance().addBlock("Block 2").toString());
}
}
看起來沒什么問題:
{"blkNum":1,"curBlockHash":"db27dd5c1e51197f6e9580613d9dbd5198a053b8c92da6560538579834e83159","data":"Genesis Block","prevBlockHash":"00000000000000000","timeStamp":"2020-05-16 17:09:10"}
{"blkNum":2,"curBlockHash":"bc6a75cf858241503a64ebdc5cf21ddcb187e6759c016b906f288cdac26ccae2","data":"Block 2","prevBlockHash":"db27dd5c1e51197f6e9580613d9dbd5198a053b8c92da6560538579834e83159","timeStamp":"2020-05-16 17:09:10"}
后一篇文章: 搭建你的第一個區塊鏈網絡(二)
Github倉庫地址在這里,隨時保持更新中.....
Github地址:Jchain