用Java程式碼實現區塊鏈技術

Gb16978發表於2022-07-18

首先讓我們快速總結一下區塊鏈。一個塊包含一些標題資訊和一組或一塊任何型別資料的事務。鏈從第一個(起源)塊開始。在新增/追加事務時,將根據一個塊中可以儲存的事務數量建立新的塊。


當超過塊閾值大小時,將建立一個新的事務塊。新區塊與前一區塊相連,因此稱為區塊鏈。


不變性

區塊鏈是不可變的,因為為交易計算SHA-256雜湊。塊的內容也會被雜湊,從而提供唯一的識別符號。此外,來自連結的前一個塊的雜湊也被儲存並雜湊在塊頭中。


這就是為什麼試圖篡改區塊鏈區塊基本上是不可能的,至少在目前的計算能力下是如此。下面是一個顯示塊屬性的部分Java類定義。

...

public class Block<T extends Tx> {

public long timeStamp;

private int index;

private List<T> transactions = new ArrayList<T>();

private String hash;

private String previousHash;

private String merkleRoot;

private String nonce = "0000";

// caches Transaction SHA256 hashes

    public Map<String,T> map = new HashMap<String,T>();

...

請注意,注入的泛型型別是Tx型別。這允許事務資料發生變化。此外, previousHash 屬性將引用前一個塊的雜湊。 merkleRoot 和 nonce 屬性將在稍後進行描述。


塊雜湊

每個塊可以計算一個塊雜湊。這本質上是連線在一起的所有塊屬性的雜湊,包括前一個塊的雜湊和由此計算出的SHA-256雜湊。


下面是塊中定義的方法。計算雜湊的java類。


...

public void computeHash() {

     Gson parser = new Gson(); // probably should cache this instance

     String serializedData = parser.toJson(transactions);   

     setHash(SHA256.generateHash(timeStamp + index + merkleRoot + serializedData + nonce + previousHash));

     }

...

塊事務被序列化為JSON字串,以便在雜湊之前將其附加到塊屬性中。


Chain 鏈

區塊鏈透過接受交易來管理區塊。當達到預定閾值時,建立塊。這是一個簡單的Chain鏈。java部分實現:


...

public class SimpleBlockchain<T extends Tx> {

public static final int BLOCK_SIZE = 10;

public List<Block<T>> chain = new ArrayList<Block<T>>();


public SimpleBlockchain() {

// create genesis block

chain.add(newBlock());

}


...

注意,chain屬性包含使用Tx型別鍵入的塊的列表。此外,在建立鏈時,無引數建構函式會建立一個初始的“ genesis ”塊。下面是 newBlock() 方法的原始碼。


public Block<T> newBlock() {

int count = chain.size();

String previousHash = "root";


if (count > 0)

previousHash = blockChainHash();


Block<T> block = new Block<T>();


block.setTimeStamp(System.currentTimeMillis());

block.setIndex(count);

block.setPreviousHash(previousHash);

return block;

}

這個新的block方法將建立一個新的block例項,為適當的值設定種子,並分配前一個block的hash(即鏈頭的hash)。然後它將返回塊。


在將塊新增到鏈之前,可以透過將新塊的上一個雜湊與鏈的最後一個塊(頭)進行比較來驗證塊,以確保它們匹配。這是一個簡單的鎖鏈。java方法描述了這一點。


public void addAndValidateBlock(Block<T> block) {


// compare previous block hash, add if valid

Block<T> current = block;

for (int i = chain.size() - 1; i >= 0; i--) {

Block<T> b = chain.get(i);

if (b.getHash().equals(current.getPreviousHash())) {

current = b;

} else {


throw new RuntimeException("Block Invalid");

}


}


this.chain.add(block);

}

整個區塊鏈透過鏈的迴圈進行驗證,以確保一個區塊的雜湊仍然與前一個區塊的雜湊匹配。


這是 SimpleBlockChain.java 的 validate() 方法實現。


public boolean validate() {


String previousHash = null;

for (Block<T> block : chain) {

String currentHash = block.getHash();

if (!currentHash.equals(previousHash)) {

return false;

}


previousHash = currentHash;


}


return true;


}

你可以看到,試圖以任何方式偽造交易資料或任何其他財產都是非常困難的。而且,隨著鏈條的增長,它繼續變得非常、非常、非常困難,基本上是不可能的。直到量子計算機問世


新增事務

區塊鏈技術的另一個重要技術點是它是分散式的。它們是附加的這一事實只會有助於在參與區塊鏈網路的節點之間複製區塊鏈。節點通常以點對點的方式進行通訊,比特幣就是這樣,但不一定要這樣。其他區塊鏈實施使用分散的方法,比如透過HTTP使用API。然而,這是另一個部落格的主題。


事務幾乎可以代表任何東西。事務可以包含要執行的程式碼(即智慧合約),或者儲存和附加有關某種業務事務的資訊。


智慧合同:旨在以數字方式促進、驗證或強制執行合同談判或履行的計算機協議。


就比特幣而言,交易包含從所有者賬戶到其他賬戶的金額(即在賬戶之間轉移比特幣金額)。交易中還包括公鑰和帳戶ID,因此傳輸是安全的。但這是比特幣特有的。


將交易新增到網路併合並;它們不在一個區塊或鏈條中。


這就是區塊鏈共識機制發揮作用的地方。這裡有許多經過驗證的共識演算法和模式,超出了本部落格的範圍。


挖掘是比特幣區塊鏈使用的共識機制。這就是本部落格進一步討論的共識型別。共識機制收集事務,用它們構建塊,然後將塊新增到鏈中。然後,鏈在新增到鏈之前驗證新的事務塊。


Merkle樹

事務被雜湊並新增到塊中。建立Merkle樹資料結構來計算Merkle根雜湊。每個塊將儲存Merkle樹的根,這是一個平衡的雜湊二叉樹,其中內部節點是兩個子雜湊的雜湊,一直到根雜湊,即Merkle根。




此樹用於驗證塊事務,如果在任何事務中更改了單個資訊位,Merkle根將無效。此外,它們還可以幫助以分散式方式傳輸塊,因為該結構只允許新增和驗證整個事務塊所需的事務雜湊的單個分支。


下面是模組中的方法。從事務列表中建立Merkle樹的java類。


public List<String> merkleTree() {

ArrayList<String> tree = new ArrayList<>();

// Start by adding all the hashes of the transactions as leaves of the

// tree.

for (T t : transactions) {

tree.add(t.hash());

}

int levelOffset = 0; // Offset in the list where the currently processed

// level starts.

// Step through each level, stopping when we reach the root (levelSize

// == 1).

for (int levelSize = transactions.size(); levelSize > 1; levelSize = (levelSize + 1) / 2) {

// For each pair of nodes on that level:

for (int left = 0; left < levelSize; left += 2) {

// The right hand node can be the same as the left hand, in the

// case where we don't have enough

// transactions.

int right = Math.min(left + 1, levelSize - 1);

String tleft = tree.get(levelOffset + left);

String tright = tree.get(levelOffset + right);

tree.add(SHA256.generateHash(tleft + tright));

}

// Move to the next level.

levelOffset += levelSize;

}

return tree;

}

該方法用於計算塊的Merkle樹根。配套專案有一個Merkle樹單元測試,它試圖將事務新增到塊中,並驗證Merkle根是否已更改。下面是單元測試的原始碼。


@Test

public void merkleTreeTest() {


// create chain, add transaction


SimpleBlockchain<Transaction> chain1 = new SimpleBlockchain<Transaction>();


chain1.add(new Transaction("A")).add(new Transaction("B")).add(new Transaction("C")).add(new Transaction("D"));


// get a block in chain

Block<Transaction> block = chain1.getHead();


System.out.println("Merkle Hash tree :" + block.merkleTree());


// get a transaction from block

Transaction tx = block.getTransactions().get(0);


// see if block transactions are valid, they should be

block.transasctionsValid();

assertTrue(block.transasctionsValid());


// mutate the data of a transaction

tx.setValue("Z");


// block should no longer be valid, blocks MerkleRoot does not match computed merkle tree of transactions

assertFalse(block.transasctionsValid());


}


示例Java專案( )有一個 Miner.java 類,帶有一個 proofwork(Block) 方法實現,如下所示。


private String proofOfWork(Block block) {


String nonceKey = block.getNonce();

long nonce = 0;

boolean nonceFound = false;

String nonceHash = "";


Gson parser = new Gson();

String serializedData = parser.toJson(transactionPool);

String message = block.getTimeStamp() + block.getIndex() + block.getMerkleRoot() + serializedData

+ block.getPreviousHash();


while (!nonceFound) {


nonceHash = SHA256.generateHash(message + nonce);

nonceFound = nonceHash.substring(0, nonceKey.length()).equals(nonceKey);

nonce++;


}


return nonceHash;


}

同樣,這是簡化的,但是一旦收到一定數量的事務,miner實現將對塊執行工作證明雜湊。該演算法只是迴圈並建立塊的SHA-256雜湊,直到產生前導數雜湊。


這可能需要很多時間,這就是為什麼要實現特定的GPU微處理器來儘可能快地執行和解決這個問題。


單元測試

您可以在GitHub上看到所有這些概念與Java示例專案的JUnit測試結合在一起。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70019421/viewspace-2906140/,如需轉載,請註明出處,否則將追究法律責任。

相關文章