搭建你的第一個區塊鏈網絡(一):區塊結構


寫一個系列文章,由簡入深搭建一個區塊鏈網絡,也是從零開始開發一個開源項目。
不再介紹區塊鏈的基礎知識了,所以希望讀者提前了解區塊鏈的基礎知識,項目是使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM