區塊鏈這么火,咱也跟個風,
一、前言
最近,銀行總行關于數字貨幣即將推出的訊息頻傳,把BTC也帶得來了一波反彈,
借著這個風,我們也研究一下區塊鏈,
通常大家說到區塊鏈,實際包括兩部分概念:
第一個概念,就是狹義上的區塊鏈,聽起來很高大上又很復雜,但追根到底,它就是一種加密應用,
提起加密,我們腦袋里會顯現出:DES、3DES、AES、RSA、DSA、SHA-1、MD5……很多很多,
狹義的區塊鏈,其實就是使用這些加密技術而形成的一種應用,
這個應用又分為兩個部分:
- 區塊
區塊就是存放資料的一個獨立空間,
不好理解?舉個例子:我們在紙上寫個作文,寫了好幾篇,那每一篇紙上,都會有一些我們寫的內容,這個內容,就是資料,而這張紙,就是一個區塊,
所以,區塊就是放某些資料的一個特定的獨立的空間,
根據需要,一個資料可以放在一個區塊上,也可以放在多個區塊上,同時,一個區塊可以只存放一個資料,也可以存放很多個資料,這兒不需要太糾結怎么放,自己決定就好,區塊鏈關注的是資料的存放方式,而不是資料本身,
- 鏈
鏈這個概念更簡單,就是把上面說的區塊,用一個鏈表記錄下來,
既然說到鏈表,就能想到,在鏈表上記錄的區塊,是有次序的,此外,最重要的是,鏈里的每一個區塊,在記錄資料的同時,也同時記錄了他的前一個區塊的資訊(在區塊鏈里,稱之為指紋),
換句話說就是,每個區塊里,都記錄著這個區塊前邊所有區塊的資訊,同時,每個區塊,都對這個區塊后邊的所有區塊產生影響,
這樣的設計,會形成這樣的效果:當改變一個區塊的資料時,需要同時把這個區塊后邊所有區塊的指紋資訊全部進行同步更新,如果僅僅只改變這個區塊本身的內容,那后邊的區塊會很容易通過指紋來驗證這個區塊非法和無效,
第二個概念,是分布式存盤
上面區塊鏈的概念中,在資料保存上有一個漏洞:如果一個非法用戶真的把一個區塊以及這個區塊后邊的所有區塊都修改了,那他就改變了這個區塊鏈里保存的資料,怎么破?
一個有效的方式,就是分布式存盤,把這樣一個鏈,存放在很多個地方,每個地方都有這個鏈的一個副本,系統驗證一個區塊是否合法,除了驗證鏈的合法性外,還需要驗證這個區塊在各處保存的副本是否一致,系統認可超過半數一致的區塊為合法區塊,
這樣,非法用戶如果想改變一個區塊的資料,不僅需要修改這個鏈,同時還需要把這個鏈在各處的副本中半數以上的記錄也修改了,當這個副本的數量很大時,這將變成一個不可能完成的任務,
當然,在互聯網上,安全永遠是相對的,去年幣圈最大的事件,就是真的有一幫子黑客,利用廉價的服務器,造出了超過半數的區塊鏈副本,然后修改區塊資料,并讓這些超過半數的副本認可并覆寫了正常的區塊鏈資料,從而盜取了大量的數字幣并拋售,
這是題外話,
區塊鏈的概念就說到這里,
今天的代碼,我們僅研究區塊鏈的原理和方法,分布式存盤,有興趣的話,可以研究一下P2P的種子結構和下載原理,路數是一樣的,
下面上代碼,
為了防止不提供原網址的轉載,特在這里加上原文鏈接:https://www.cnblogs.com/tiger-wang/p/12966882.html
二、開發環境&基礎工程
這個Demo的開發環境是:Mac + VS Code + Dotnet Core 3.1.2,
$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.201
Commit: b1768b4ae7
Runtime Environment:
OS Name: Mac OS X
OS Version: 10.15
OS Platform: Darwin
RID: osx.10.15-x64
Base Path: /usr/local/share/dotnet/sdk/3.1.201/
Host (useful for support):
Version: 3.1.3
Commit: 4a9f85e9f8
.NET Core SDKs installed:
3.1.201 [/usr/local/share/dotnet/sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
首先,在這個環境下建立工程:
- 創建Solution
% dotnet new sln -o demo
The template "Solution File" was created successfully.
- 這次,我們用Console創建工程
% cd demo
% dotnet new webapi -o demo
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on demo/demo.csproj...
Determining projects to restore...
Restored demo/demo.csproj (in 170 ms).
Restore succeeded.
基礎工程搭建完成,
三、創建區塊Model
在工程下面,創建一個目錄Models,并在目錄下建立類Block.cs:
public class Block
{
public DateTimeOffset time_stamp { get; set; }
public object data { get; set; }
public string pre_hash { get; set; }
public string hash { get; set; }
public string nonce { get; set; }
}
解釋一下各個欄位:
time_stamp:時間戳,也就是這個區塊的創建時間
data:資料,可以是任意型別,是我們要用區塊鏈來保存的資料
pre_hash:前一個區塊的hash值
hash:當前區塊的hash值
nonce:亂數
在這幾個欄位中,真正在區塊鏈中起作用的是后面三個欄位:pre_hash、hash、nonce,
在計算中,hash值是由這個區塊的pre_hash、data、time_stamp、nonce四個欄位共同計算產生,
這樣做,一方面,我們通過hash值可以驗證保存的資料data,同時,也把前一個區塊的hash資訊保存到了這個區塊中,
nonce欄位在這個demo中,實際意義不大,但在實際專案中,卻有它的實用價值,比方BTC中,要求hash值有特定的格式(至少前8個位元組全是0),需要通過改變nonce的值,來得到這樣的hash,又因為hash無法逆向計算,所以只能用窮舉法修改nonce,一個一個計算并測驗hash,這個程序叫WK,
四、創建鏈
有了區塊model,創建鏈很簡單,
我們創建一個BlockChains類,并在里面用SortedList建立一個鏈,
public class BlockChains
{
private static SortedList<int, Block> _block_chains = new SortedList<int, Block>();
}
鏈也建完了,
后面,我們會在這個鏈中實作對于區塊鏈的各種處理方法,
五、往鏈中增加區塊
下面我們在BlockChains類中寫一個往鏈中增加區塊的方法:
private static string _hash_zero = "Initialize_Hash_By_WangPlus";
public bool addBlockData(object data)
{
Block new_block = new Block()
{
time_stamp = DateTimeOffset.Now,
data = data,
nonce = $"{_random.Next(9999):D4}",
};
new_block.pre_hash = _block_chains.Count <= 0 ? _hash_zero : _block_chains.Last().Value.hash;
new_block.hash = calculateHash(new_block);
_block_chains.Add(_block_chains.Count + 1, new_block);
return true;
}
private string calculateHash(Block block)
{
if (block == null)
return string.Empty;
string data_json = JsonConvert.SerializeObject(block.data, Formatting.None);
string block_string = $"{block.time_stamp.Ticks.ToString()}|{block.pre_hash}|{data_json}|{block.nonce}";
var block_hash = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(block_string));
return Convert.ToBase64String(block_hash);
}
在這個實作的方法中,
- 第一個區塊需要特殊處理,因為他的
pre_hash不存在,所以我們給了一個默認的串, - 計算
hash時,我們把區塊的time_stamp、pre_hash、data、nonce全都包含在里面了,
六、驗證區塊
也是一個方法,加在BlockChains中:
public bool isBlockValid(int index)
{
if (index <= 0 || index > _block_chains.Count)
return false;
if ((index > 1 && _block_chains[index].pre_hash != _block_chains[index - 1].hash) || (index == 1 && _block_chains[index].pre_hash != _hash_zero))
return false;
if (_block_chains[index].hash != calculateHash(index))
return false;
return true;
}
private string calculateHash(int index)
{
return calculateHash(_block_chains[index]);
}
這個Demo中,沒有實作分布存盤,所以驗證區塊的部分,我們只做了簡單驗證:驗證當前區塊和前一個區塊的hash是否匹配,
做到這兒,這個簡單的區塊鏈Demo就完成了,
七、總結和思考
上面是一個簡單的區塊鏈應用中,區塊鏈概念的實作,
在實際應用中,我們需要理解以下內容:
- 區塊鏈是一個加密技術,它本身跟資料無關;
- 區塊鏈在形成后,是一個只讀鏈,就是說在通常情況下,我們不會從一個鏈中修改或洗掉一個區塊,因為這會導致后續所有區塊的修改,這個代價很大;
- 因為區塊不可更改,所以區塊中存盤的資料也不可更改,如果保存的資料有錯,通常是采用類似記帳的方式,用反沖記錄去消除這個錯誤,而不是修改區塊鏈;
- 區塊鏈應用中,在安全級別要求比較高的情況下,應該把開發重點放在分布存盤上面,
上面Demo的代碼已傳到Github,
代碼地址:https://github.com/humornif/Demo-Code/tree/master/0010/demo
(全文完)
![]() |
微信公眾號:老王Plus 掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送 本文著作權歸作者所有,轉載請保留此宣告和原文鏈接 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/24110.html
標籤:.NET Core
上一篇:ketchup服務治理

