正如我們所知,區(qū)塊鏈的設(shè)計(jì)是不可變的。在這里,我們將設(shè)計(jì)一個(gè)簡單的區(qū)塊鏈,它將幫助您理解散列如何使區(qū)塊鏈不可變,只需幾行JAVA代碼。
注:這只是一個(gè)演示區(qū)塊鏈,真正的區(qū)塊鏈涉及很多其他東西,如共識(shí)機(jī)制、數(shù)字簽名、Merkle樹等。。此代碼示例將有助于實(shí)現(xiàn)理想的目的。
區(qū)塊鏈中的第一個(gè)區(qū)塊是Genesis區(qū)塊。genesis區(qū)塊幾乎總是硬編碼到利用其區(qū)塊鏈的應(yīng)用程序的軟件中。
對(duì)于隨后生成的每個(gè)新塊,我們將使用前一個(gè)塊的哈希以及它自己的事務(wù)作為輸入來確定它的塊哈希。
Object[] contents ={Arrays.hashCode(transactions),previousHash};
blockHash = Arrays.hashCode(contents);
散列函數(shù)是一種數(shù)學(xué)函數(shù),它接受任意長度數(shù)值數(shù)據(jù)的輸入,并將其轉(zhuǎn)換為固定長度的數(shù)值數(shù)據(jù)。
不同的散列函數(shù)使用不同的算法生成散列值。
此外,哈希函數(shù)將始終為任何特定輸入提供相同的輸出。但是,如果您在輸入中做了一點(diǎn)小的更改,那么產(chǎn)生的哈希值將與前一個(gè)完全不同。
記住散列不是加密。
在加密中,一旦加密了數(shù)據(jù),就可以通過解密將其取回,而在散列中,則無法通過任何方法將輸入取回。
您可能會(huì)想知道為什么需要像SHA256(安全哈希算法)這樣的哈希算法?
最重要的原因是這些算法幫助我們避免沖突(不同輸入的哈希值相似)。
現(xiàn)在,讓我們通過代碼來了解區(qū)塊鏈如何使塊的散列無法更改,從而使塊一旦寫入?yún)^(qū)塊鏈,就無法更改。
我們將創(chuàng)建一個(gè)塊類。每個(gè)塊將有:
- 交易清單(int)
- 上一個(gè)塊哈希(String[])
- 散列(int)
對(duì)變量塊類應(yīng)用 getter setter 方法后,如下所示:
import java.util.Arrays;
public class Block
{
private int previousHash;
private String[] transactions;
private int blockHash;
public Block(int previousHash, String[] transactions) {
this.previousHash = previousHash;
this.transactions = transactions;
Object[] contents = {Arrays.hashCode(transactions),previousHash};
this.blockHash = Arrays.hashCode(contents);
}
public int getPreviousHash() {
return previousHash;
}
public String[] getTransactions() {
return transactions;
}
public int getBlockHash() {
return blockHash;
}
public void setPreviousHash(int previousHash) {
this.previousHash = previousHash;
}
public void setTransactions(String[] transactions) {
this.transactions = transactions;
}
public void setBlockHash(int blockHash) {
this.blockHash = blockHash;
}
}
現(xiàn)在讓我們創(chuàng)建一個(gè)區(qū)塊鏈。
我們將從創(chuàng)建Genesis塊開始。由于Genesis塊是鏈中的第一個(gè)塊,我們將硬編碼事務(wù)和以前的哈希值。
真正的區(qū)塊鏈中的交易肯定是某種交易類別,將使用不同的數(shù)據(jù)結(jié)構(gòu)。為了簡單起見,我將它們寫成字符串。
主類如下所示:
import java.util.ArrayList;
public class Blockchain {
ArrayList<Block> blockchain = new ArrayList<>();
public static void main(String[] args) {
String[] genesisTransactions = {"Suraj sent Ruja 1542 Bitcoins","Ruja sent 10 Bitcoins to John"};
Block genesisBlock = new Block(0,genesisTransactions);
System.out.println("Genesis Block Hash:"+genesisBlock.getBlockHash());
String[] block2Transactions = {"John sent 10 bitcoins to Suraj","Suraj sent 10 bitcoins to Alex"};
Block block2= new Block(genesisBlock.getBlockHash(), block2Transactions);
System.out.println("Block2 Hash:"+block2.getBlockHash());
String[] block3Transactions = {"Alex sent 999 bitcoins to non"};
Block block3 = new Block(block2.getBlockHash(), block3Transactions);
System.out.println("Block3 Hash:"+block3.getBlockHash());
}
}
輸出:
Genesis Block Hash:-1106827926
Block2 Hash:957910147
Block3 Hash:-716750945
您可以輸出genesis block的HashCode并更改它,您將看到輸出與以前的輸出有很大不同,即使您更改事務(wù)字符串中單個(gè)字母的大小寫。
將genesis block事務(wù)中“Suraj”的“S”更改為“S”后的輸出:
Genesis Block Hash:1528835466
Block2 Hash:-701393757
Block3 Hash:1918912447
這就是塊鏈的形成方式,每個(gè)新塊散列都指向它之前的塊散列。這種散列系統(tǒng)保證歷史記錄中的任何事務(wù)都不會(huì)被篡改,因?yàn)槿绻聞?wù)的任何單個(gè)部分發(fā)生更改,那么它所屬的塊的散列以及隨后任何塊的散列也會(huì)發(fā)生更改。
因此很容易捕獲任何篡改,因?yàn)槟恍璞容^散列即可。