現成雜湊遊戲系統原始碼搭建丨演示版案例

aa111111發表於2023-02-27

不變性

區塊鏈是不可變的,因為為交易計算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。然而,這是另一個部落格的主題。


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


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


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());


}


採礦工作證明

將交易組合成一個區塊,然後提交給鏈成員驗證的過程在比特幣領域被稱為“挖掘”。


更一般地說,在區塊鏈中,這被稱為共識。有不同型別的經驗證的分散式一致性演算法。使用哪種機制取決於您是否擁有公共區塊鏈或許可區塊鏈。我們的白皮書對此進行了更深入的描述,但本部落格的重點是區塊鏈機制,因此本例我們將應用一種工作證明共識機制。


因此,挖掘節點將監聽區塊鏈正在執行的交易,並執行一個簡單的數學謎題。這個謎題使用一個在每次迭代中都會更改的nonce值生成具有一組預先確定的前導零的塊雜湊,直到找到前導零雜湊為止。


示例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;


}


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

相關文章