.Net Core實現區塊鏈初探

来源:https://www.cnblogs.com/tiger-wang/archive/2020/05/27/12966882.html
-Advertisement-
Play Games

區塊鏈這麼火,咱也跟個風。 一、前言 最近,銀行總行關於數字貨幣即將推出的消息頻傳,把BTC也帶得來了一波反彈。 藉著這個風,我們也研究一下區塊鏈。 通常大家說到區塊鏈,實際包括兩部分概念: 第一個概念,就是狹義上的區塊鏈。聽起來很高大上又很複雜,但追根到底,它就是一種加密應用。 提起加密,我們腦袋 ...


區塊鏈這麼火,咱也跟個風。

一、前言

最近,銀行總行關於數字貨幣即將推出的消息頻傳,把BTC也帶得來了一波反彈。

藉著這個風,我們也研究一下區塊鏈。

通常大家說到區塊鏈,實際包括兩部分概念:

第一個概念,就是狹義上的區塊鏈。聽起來很高大上又很複雜,但追根到底,它就是一種加密應用。

提起加密,我們腦袋裡會顯現出:DES、3DES、AES、RSA、DSA、SHA-1、MD5……很多很多。

狹義的區塊鏈,其實就是使用這些加密技術而形成的一種應用

這個應用又分為兩個部分:

  1. 區塊

區塊就是存放數據的一個獨立空間。

不好理解?舉個例子:我們在紙上寫個作文,寫了好幾篇。那每一篇紙上,都會有一些我們寫的內容。這個內容,就是數據。而這張紙,就是一個區塊。

所以,區塊就是放某些數據的一個特定的獨立的空間。

根據需要,一個數據可以放在一個區塊上,也可以放在多個區塊上。同時,一個區塊可以只存放一個數據,也可以存放很多個數據。這兒不需要太糾結怎麼放,自己決定就好。區塊鏈關註的是數據的存放方式,而不是數據本身

鏈這個概念更簡單,就是把上面說的區塊,用一個鏈表記錄下來。

既然說到鏈表,就能想到,在鏈表上記錄的區塊,是有次序的。此外,最重要的是,鏈里的每一個區塊,在記錄數據的同時,也同時記錄了他的前一個區塊的信息(在區塊鏈里,稱之為指紋)。

換句話說就是,每個區塊里,都記錄著這個區塊前邊所有區塊的信息,同時,每個區塊,都對這個區塊後邊的所有區塊產生影響。

這樣的設計,會形成這樣的效果:當改變一個區塊的數據時,需要同時把這個區塊後邊所有區塊的指紋信息全部進行同步更新。如果僅僅只改變這個區塊本身的內容,那後邊的區塊會很容易通過指紋來驗證這個區塊非法和無效。

第二個概念,是分散式存儲

上面區塊鏈的概念中,在數據保存上有一個漏洞:如果一個非法用戶真的把一個區塊以及這個區塊後邊的所有區塊都修改了,那他就改變了這個區塊鏈里保存的數據。怎麼破?

一個有效的方式,就是分散式存儲。把這樣一個鏈,存放在很多個地方,每個地方都有這個鏈的一個副本。系統驗證一個區塊是否合法,除了驗證鏈的合法性外,還需要驗證這個區塊在各處保存的副本是否一致。系統認可超過半數一致的區塊為合法區塊。

這樣,非法用戶如果想改變一個區塊的數據,不僅需要修改這個鏈,同時還需要把這個鏈在各處的副本中半數以上的記錄也修改了。當這個副本的數量很大時,這將變成一個不可能完成的任務。

當然,在互聯網上,安全永遠是相對的。去年幣圈最大的事件,就是真的有一幫子黑客,利用廉價的伺服器,造出了超過半數的區塊鏈副本,然後修改區塊數據,並讓這些超過半數的副本認可並覆蓋了正常的區塊鏈數據,從而盜取了大量的數字幣並拋售。

這是題外話。

區塊鏈的概念就說到這裡。

今天的代碼,我們僅研究區塊鏈的原理和方法。分散式存儲,有興趣的話,可以研究一下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]

首先,在這個環境下建立工程:

  1. 創建Solution
% dotnet new sln -o demo
The template "Solution File" was created successfully.
  1. 這次,我們用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);
}

在這個實現的方法中,

  1. 第一個區塊需要特殊處理,因為他的pre_hash不存在,所以我們給了一個預設的串。
  2. 計算hash時,我們把區塊的time_stamppre_hashdatanonce全都包含在裡面了。

六、驗證區塊

也是一個方法,加在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就完成了。

七、總結和思考

上面是一個簡單的區塊鏈應用中,區塊鏈概念的實現。

在實際應用中,我們需要理解以下內容:

  1. 區塊鏈是一個加密技術,它本身跟數據無關;
  2. 區塊鏈在形成後,是一個只讀鏈,就是說在通常情況下,我們不會從一個鏈中修改或刪除一個區塊。因為這會導致後續所有區塊的修改,這個代價很大;
  3. 因為區塊不可更改,所以區塊中存儲的數據也不可更改。如果保存的數據有錯,通常是採用類似記帳的方式,用反衝記錄去消除這個錯誤,而不是修改區塊鏈;
  4. 區塊鏈應用中,在安全級別要求比較高的情況下,應該把開發重點放在分佈存儲上面。

上面Demo的代碼已傳到Github。

代碼地址:https://github.com/humornif/Demo-Code/tree/master/0010/demo

(全文完)

 


 

微信公眾號:老王Plus

掃描二維碼,關註個人公眾號,可以第一時間得到最新的個人文章和內容推送

本文版權歸作者所有,轉載請保留此聲明和原文鏈接


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • IsPostBack:獲取一個值,該值指示頁是第一次呈現還是為了響應回發而載入。 一般的話如果第一次請求是get的話,那麼IsPostBack會為false,如果接下來post請求,則為true;這樣可以區分第一次和其他按鈕請求的情況。 但今天使用jQuery在主頁面的一個超鏈接post調用子頁面的 ...
  • .Net 提交頁面,js修改的Label值會丟掉 版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。 本文鏈接:https://blog.csdn.net/chenghaibing2008/article/details/9011043 當用js ...
  • C#實現密文解密 簡介:此方法一般用於對密碼加密後的解密。 代碼: private static string GetPwd(string pwd) { var sRet = string.Empty; for (int i = 0; i < pwd.Length; i++) { sRet = sR ...
  • 無論ORM有多麼強大,總會出現一些特殊的情況,它無法滿足我們的要求。在這篇文章中,我們介紹幾種執行SQL的方法。 表結構 在具體內容開始之前,我們先簡單說明一下要使用的表結構。 public class Category { public int CategoryID { get; set; } p ...
  • 我最近發現一個問題,當應用程式關閉時,我們的應用程式沒有正確執行在IHostedService中的StopAsync方法。經過反覆驗證發現,這是由於某些服務對關閉信號做出響應所需的時間太長導致的。在這篇文章中,我將展示出現這個問題的一個示例,並且會討論它為什麼會發生以及如何避免這種情況出現。 作者: ...
  • 0. 前言 之前四篇介紹了一個國內開發者開發的優秀框架SqlSugar,給我們眼前一亮的感覺。這一篇,我們將試試另一個出鏡率比較高的ORM框架-Dapper。 Dapper是一個輕量級的ORM框架,其以高速、簡單易用為特點。在某些時候,效率甚至可以與ADO.NET 媲美。那麼,吹得天花亂墜,就讓我們 ...
  • 這篇文章介紹離散式關鍵幀,並使用它做些有趣的動畫。 1. 什麼是離散式關鍵幀 以DoubleAnimationUsingKeyFrames為例,它支持四種Double的關鍵幀,其中EasingDoubleKeyFrame、LinearDoubleKeyFrame和SplineDoubleKeyFra ...
  • 上一篇文章(https://www.cnblogs.com/meowv/p/12956696.html)成功使用了Redis緩存數據,大大提高博客的響應性能。 接下來,將完成一個任務調度中心,關於定時任務有多種處理方式,如果你的需求比較簡單,比如就是單純的過多少時間迴圈執行某個操作,可以直接使用.n ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...