區(qū)塊鏈邏輯:根據(jù)所需信息創(chuàng)建一個區(qū)塊,再利用定義的計算hash值方法,不斷進行計算,直到達到想要的結(jié)果,再通過層層驗證,加入到我們的區(qū)塊鏈中。
1.設(shè)置好成員屬性
?
//區(qū)塊鏈
List<Block> blockchain = new ArrayList<>();
//哈希值,判斷挖礦成功與否
private String hash;
//前塊哈希值,便于之后驗證成功與否
private String previousHash;
//所需存儲數(shù)據(jù)
private String data;
//時間戳
private long timeStamp;
//用于判斷”挖礦“成功的密碼學(xué)數(shù)字
private int nonce;
//構(gòu)析方法,得到所需信息
public Block(String data,String previousHash,long timeStamp){
this.data = data;
this.previousHash = previousHash;
this.timeStamp = timeStamp;
this.hash = calculateBlockHash();
}
2.計算hash值方法(“挖礦”方法)
所謂挖礦,就是進行不斷地計算,直到“挖到”,而這步算法我們是借助hash算法完成的。
//得到對應(yīng)hash字符串
//hash算法優(yōu)勢:輸出格式一致,而且對數(shù)的變化十分敏感,對于之后驗證挖礦成功與否作用巨大!
public String calculateBlockHash(){
//生成獨屬的字符串,方便之后轉(zhuǎn)換
String dataToHash = previousHash + Long.toString(timeStamp)
+ Integer.toString(nonce) + data;
MessageDigest digest = null;
byte[] bytes = null;
try {
//創(chuàng)建一個提供信息摘要算法的對象,初始化為SHA-256算法對象
digest = MessageDigest.getInstance("SHA-256");
//用對象調(diào)用,信息摘要計算方法,計算后獲得字節(jié)數(shù)組
//dataToHash.getBytes(UTF_8),將字符串轉(zhuǎn)換為字節(jié)數(shù)組
bytes = digest.digest(dataToHash.getBytes(UTF_8));
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
//用緩存字符串
StringBuffer buffer = new StringBuffer();
for (byte b : bytes) {
//延伸字符串
//String.format("%02x", b),以十六進制輸出,2為指定的輸出字段的寬度.如果位數(shù)小于2,則左端補0
buffer.append(String.format("%02x", b));
}
//返回字符串
return buffer.toString();
}
3.設(shè)置好挖礦成功的條件
老實說,“挖礦”這件事本身已經(jīng)很抽象了,但是我們還需要沿著這條路,來考慮一個“挖到了”的情形。在我們“挖礦”實際是計算區(qū)塊hash值的情形下,而我們的思路是:找到以四個0開頭的hash值。
//定義了一個前綴4,這實際上意味著我們希望哈希以4個零開始。
int prefix = 4;
String prefixString = new String(new char[prefix]).replace('\0', '0');
4.“挖到”方法
這里就體現(xiàn)了hash算法的價值,僅僅通過給nonce++,就可以顯著的改變hash值,讓其前綴可能達到“0000”。
而且由于只有nonce值并沒有提供任何信息,所以對其進行賦值操作,完全沒有問題。
//開挖
public String mineBlock(int prefix){
//創(chuàng)建一個有perfix個的“0”的字符串
String prefixString = new String(new char[prefix]).replace('\0','0');
//找到開頭有perfix多個0的字符串
//substring方法是,從字符串幾位讀到幾位
while(!hash.substring(0,prefix).equals(prefixString)){
//決定那個塊
nonce++;
//通過nonce變化,更新hash值
hash = calculateBlockHash();
}
//找到了
return hash;
}
5.添加一個區(qū)塊
//在區(qū)塊鏈里添加一個塊
public void givenBlockchain_whenNewBlockAdded_thenSuccess() {
//建立一個區(qū)塊
Block newBlock = new Block(
"The is a New Block.",
blockchain.get(blockchain.size() - 1).getHash(),
new Date().getTime());
//找到四個0的區(qū)塊
newBlock.mineBlock(prefix);
//再次檢驗是否正確
assertTrue(newBlock.getHash().substring(0, prefix).equals(prefixString));
//添加一個區(qū)塊
blockchain.add(newBlock);
}
6.區(qū)塊鏈驗證
為了保證區(qū)塊的可靠性,我們就進行了多次驗證,保證絕對正確。
驗證:添加區(qū)塊的hash值是否等于hash算法所得——》
添加區(qū)塊的前區(qū)塊hash值是否等于前區(qū)塊的值——》
添加區(qū)塊的hash值是否以“0000”開頭文章來源:http://www.zghlxwxcb.cn/news/detail-784559.html
//區(qū)塊鏈驗證
public void givenBlockchain_whenValidated_thenSuccess() {
boolean flag = true;
for (int i = 0; i < blockchain.size(); i++) {
//得到前區(qū)塊的hash值
String previousHash = i==0 ? "0" : blockchain.get(i - 1).getHash();
//進行真?zhèn)闻袛? //原理:判斷hash是否等于計算的hash//判斷儲存的前區(qū)塊hash是否等于真正的hash//判斷是否滿足“挖礦”成功的條件
flag = blockchain.get(i).getHash().equals(blockchain.get(i).calculateBlockHash())
&& previousHash.equals(blockchain.get(i).getPreviousHash())
&& blockchain.get(i).getHash().substring(0, prefix).equals(prefixString);
//一次不行就直接跳出
if (!flag) break;
}
//進行正確性檢驗
assertTrue(flag);
}
現(xiàn)在已經(jīng)完成了,開始制作自己的區(qū)塊鏈吧,添加一些隱私信息,讓別人無從知曉!文章來源地址http://www.zghlxwxcb.cn/news/detail-784559.html
到了這里,關(guān)于僅僅用java就能簡單實現(xiàn)區(qū)塊鏈(BlockChain)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!