[C#]使用 C# 编写自己的区块链挖矿算法
文章原文来自:Code your own blockchain mining algorithm in Go! ,原始文章通过 Go 语言来实现的,这里仍然是承接上一篇文章,来使用 C# + .Net Core 实现我们的挖矿算法。
强烈建议阅读前先阅读这篇文章
什么是加密货币挖掘?
一个加密货币的价值体现在它的稀缺性上,如果任何人都可以任意构造一个比特币,那么比特币就毫无价值,所以比特币的区块链会让参与者完成一项“工作”,根据这个工作的最终结果还分发比特币,这个过程就被叫做“挖矿”。这就类似于一个黄金矿工花一些时间来工作,然后获得一点黄金。
挖矿的原理
如果你百度/谷歌搜索 比特币挖矿的原理 的话,都会给你说是计算一个复杂的数学问题而已,但是这么说的话太笼统而且也太简单。采矿引擎如何工作这是一个重要的知识点,所以我们需要了解一些密码学知识和哈希算法相关的知识,才能知道挖矿的基本原理。
哈希/散列介绍
单向加密人类能够理解的输入,例如 Hello World ,并将其扔到某个加密函数(即所谓的复杂的数学问题),加密函数的算法越复杂,逆向工程就越困难。
例如一个 SHA - 256 的例子,这个网站可以很快的计算散列值,让我们来散列 “Hello World” 看看会得到什么结果:

不管你试验几次都会得到一样的散列值,在编程中这种被称之为幂等性。
加密算法的一个基本特性就是,它们很难通过逆向工程来得到明文结果,但是十分容易验证他们的加密结果,例如这里的 “Hello World” 很难通过逆向工程得到他的原明文结果,比特币采用的是 Double SHA-256 也就是将明文通过 SHA-256 计算过一次之后,再拿 SHA-256 针对散列值再次进行计算,在这里我们只使用 SHA-256 来进行加密。
工作证明
比特币通过让参与者散列随机的字母与数字的组合,直到计算出来的散列包含前导 0。
例如我们计算 886 的散列值可以得到如下结果:
000f21ac06aceb9cdd0575e82d0d85fc39bed0a7a1d71970ba1641666a44f530
它返回了 3 个 0 作为前缀的散列值,但是我们怎么知道 886 计算出来的散列结果产生了 3 个 0 呢?
答案是我并不需要知道。。。我需要知道矿工给我的散列值前导有几个零就好了,并不需要复杂的算法来验证整个散列值的有效性。
比特币则稍微复杂一点,它每隔 10 分钟生成一个新的区块,新区块的散列值的难度它可以动态调整,就类似于 CLR 的 GC 一样,它可以根据目前挖矿的人数来进行难度动态调整,如果挖矿的人多的话,则调高难度,少则调低。
动手开发
1.项目配置
首先新建一个 Asp.Net Core 项目,然后选择 Empty Project(空项目) 类型,建立完成后无需进行任何配置。
2.数据模型
这里我们来创建一个具体的区块数据模型,使用的是 Struct 结构体。
public struct Block
{
/// <summary>
/// 区块位置
/// </summary>
public int Index { get; set; }
/// <summary>
/// 区块生成时间戳
/// </summary>
public string TimeStamp { get; set; }
/// <summary>
/// 心率数值
/// </summary>
public int BPM { get; set; }
/// <summary>
/// 区块 SHA-256 散列值
/// </summary>
public string Hash { get; set; }
/// <summary>
/// 前一个区块 SHA-256 散列值
/// </summary>
public string PrevHash { get; set; }
/// <summary>
/// 下一个区块生成难度
/// </summary>
public int Difficulty { get; set; }
/// <summary>
/// 随机值
/// </summary>
public string Nonce { get; set; }
}
Difficulty 是一个整形,他定义了我们希望得到哈希前导 0 的数量,前导 0 越多,生成正确的散列值就越困难,我们现在从 1 开始。
Nonce 则是每次计算块散列值所需要的随机值。
3. 工作证明
我们首先添加一个新的方法来验证生成的散列值是否包含指定数量的前导 0 :
/// <summary>
/// 校验 Hash 是否有效
/// </summary>
/// <param name="hashStr">Hash 值</param>
/// <param name="difficulty">难度</param>
/// <returns></returns>
public static bool IsHashValid(string hashStr, int difficulty)
{
var bytes = Enumerable.Range(0, hashStr.Length)
.Where(n => n % 2 == 0)
.Select(n => Convert.ToByte(hashStr.Substring(n, 2), 16))
.ToArray();
var bits = new BitArray(bytes);
for (var i = 0; i < difficulty; i++)
{
if (bits[i]) return false;
}
return true;
}
然后我们更改了之前区块 Hash 的生成方法:
/// <summary>
/// 计算区块 HASH 值
/// </summary>
/// <param name="block">区块实例</param>
/// <returns>计算完成的区块散列值</returns>
public static string CalculateHash(Block block)
{
string calculationStr = $"{block.Index}{block.TimeStamp}{block.BPM}{block.PrevHash}{block.Nonce}";
SHA256 sha256Generator = SHA256.Create();
byte[] sha256HashBytes = sha256Generator.ComputeHash(Encoding.UTF8.GetBytes(calculationStr));
StringBuilder sha256StrBuilder = new StringBuilder();
foreach (byte @byte in sha256HashBytes)
{
sha256StrBuilder.Append(@byte.ToString("x2"));
}
return sha256StrBuilder.ToString();
}
在这里我们新增新增了 Nonce 随机值作为散列生成的依据。
那么我们生成新区块的时候就顺便来挖矿吧:
/// <summary>
/// 生成新的区块
/// </summary>
/// <param name="oldBlock">旧的区块数据</param>
/// <param name="BPM">心率</param>
/// <returns>新的区块</returns>
public static Block GenerateBlock(Block oldBlock, int BPM)
{
Block newBlock = new Block()
{
Index = oldBlock.Index + 1,
TimeStamp = CalculateCurrentTimeUTC(),
BPM = BPM,
PrevHash = oldBlock.Hash,
Difficulty = Difficulty
};
// 挖矿 ing...
for (int i = 0; ; i++)
{
newBlock.Nonce = i.ToString("x2");
if (!IsHashValid(CalculateHash(newBlock), Difficulty))
{
Console.WriteLine($"目前结果:{CalculateHash(newBlock)} ,正在计算中...");
Task.Delay(1);
continue;
}
else
{
Console.WriteLine($"目前结果:{CalculateHash(newBlock)} ,计算完毕...");
newBlock.Hash = CalculateHash(newBlock);
break;
}
}
// 原有代码
// newBlock.Hash = CalculateHash(newBlock);
return newBlock;
}
效果


结语
其实代码并不复杂,但是这几十行代码表明了区块链挖矿的本质,后面你可以参考原文实现 P2P 与 股权权益证明方法与智能合约。
项目代码地址:http://git.myzony.com/Zony/BlockChain.git
Code a simple P2P blockchain in Go.
[C#]使用 C# 编写自己的区块链挖矿算法的更多相关文章
- [转帖][区块链]共识算法(POW,POS,DPOS,PBFT)介绍和心得
[区块链]共识算法(POW,POS,DPOS,PBFT)介绍和心得 置顶 2017-03-12 18:31:19 乐扣老师lekkoliu 阅读数 127953 收藏 更多 分类专栏: 技术管理 区 ...
- 【原】用Java编写第一个区块链(一)
写这篇随笔主要是尝试帮助自己了解如何学习区块链技术开发. [本文禁止任何形式的全文粘贴式转载,本文来自 zacky31 的随笔] 目标: 创建一个最基本的"区块链" 实现一个简单的 ...
- 用Java编写第一个区块链
原文地址:https://www.cnblogs.com/zacky31/p/9057193.html 目标: 创建一个最基本的“区块链” 实现一个简单的挖矿系统 前提: 对面向对象编程有一定的基础 ...
- 【原】用Java编写第一个区块链(二)
这篇文章将去介绍如何使用区块链进行交易. [本文禁止任何形式的全文粘贴式转载,本文来自 zacky31 的随笔] 目标: 在上一篇文章中,我们已经创建了一个可信任的区块链.但是目前所创建的链中包含的有 ...
- [区块链] 共识算法之争(PBFT,Raft,PoW,PoS,DPoS,Ripple)
近几天对区块链中几种常见的共识机制(PBFT,Raft,PoW,PoS,DPoS,Ripple)进行了总结.尽量使用简单易懂语言,篇幅较大,想了解的可以只读每个算法介绍中前边的原理.本篇文章主要参考& ...
- 区块链共识算法 PBFT(拜占庭容错)、PAXOS、RAFT简述
共识算法 区块链中最重要的便是共识算法,比特币使用的是POS(Proof of Work,工作量证明),以太币使用的是POS(Proof of Stake,股权证明)使得算理便的不怎么重要了,而今PO ...
- 区块链共识算法|RAFT和PBFT的区别
这里有个很形象的比喻: 一个团队一定会有一个老大和普通成员.对于 raft 算法,共识过程就是:只要老大还没挂,老大说什么,我们(团队普通成员)就做什么,坚决执行.那什么时候重新老大呢?只有当老大挂了 ...
- 未来-区块链-Micron:区块链永远不会忘记:内存对这项革命性技术的推动作用
ylbtech-未来-区块链-Micron:区块链永远不会忘记:内存对这项革命性技术的推动作用 1.返回顶部 1. 俗话说,大象永远不会忘记.区块链亦是如此. 内存是区块链的核心,它是一种以关键方式构 ...
- 只用120行Java代码写一个自己的区块链-2网络
已经看完第一章的内容了吗,欢迎回来. 上一章我们介绍了关于怎么去编写自己的区块链,完成哈希和新块的校验.但是它只是在一个终端(结点)上跑.我们怎么样来连接其他结点以及贡献新的块呢,怎么样广播到其他结点 ...
随机推荐
- Unity UGUI基础之Image
UGUI的Image等价于NGUI的Sprite组件,用于显示图片. 一.Image组件: Source Image(图像源):纹理格式为Sprite(2D and UI)的图片资源(导入图片后选择T ...
- 04-GIT TortoiseGit冲突和补丁演示 案例演示
TortoiseGit安装下载 http://download.tortoisegit.org/tgit/1.8.12.0/ 或https://code.google.com/p/tortoisegi ...
- Jeff Atwood质疑iPhone的单键设计
我喜欢使用iPhone,但我对它的一个设计不敢苟同:苹果始终坚持,设备的正面永远只能有一个按键. 我还买了一个Kindle Fire,它更离谱,一个按键都没有!我完全赞成,任何小器具的正面都应该在明显 ...
- Touch Handling in Cocos2D 3.x(五)
实现新英雄的放置功能 首先我们需要一个变量来保持我们当前移动英雄的引用,因此我们将添加一个私有实例变量.修改MainScene.m中的代码. 用: @implementation MainScene ...
- leetcode之word ladder
对于之前没有接触过该类型题目的人来说,此题无疑是个难题,本人提交了10次才正确通过,期间遇到了非常多的问题,感觉几乎把OJ的所有错误遍历了一遍,下面详细说说自己做该题的经验. 首先承认,我一开始并没有 ...
- MySQL学习笔记_4_MySQL创建数据表(下)
MySQL创建数据表(下) 五.数据表类型及存储位置 1.MySQL与大多数数据库不同,MySQL有一个存储引擎概念.MySQL可以针对不同的存储需求选择不同的存储引擎. 2. showengines ...
- 【算法导论】图的广度优先搜索遍历(BFS)
图的存储方法:邻接矩阵.邻接表 例如:有一个图如下所示(该图也作为程序的实例): 则上图用邻接矩阵可以表示为: 用邻接表可以表示如下: 邻接矩阵可以很容易的用二维数组表示,下面主要看看怎样构成邻接表: ...
- Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验
Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高 ...
- 如何实现 集群化/Session 复制-doc(cluster-howto.html)
源文档链接: http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html 翻译日期: 2014年3月19日 翻译人员: 铁锚 感受: Tomc ...
- Android表格布局(Table Layout)
Android表格布局(Table Layout) 先来看布局管理器之间继承关系图: 图1 可知TableLayout继承了LinearLayout,所以表格布局本质上依然是线性管理器. 表格布局采用 ...