扣丁学堂区块链培训简述如何使用C#编写自己的区块链挖矿算法

2019-09-20 10:43:04 3213浏览

本篇文章扣丁学堂区块链培训小编给读者们介绍一下使用C#编写自己的区块链挖矿算法,对区块链挖矿算法感兴趣的小伙伴就随小编来了解一下吧,希望对小伙伴们有帮助。


扣丁学堂区块链培训简述如何使用C#编写自己的区块链挖矿算法


什么是加密货币挖掘?


一个加密货币的价值体现在它的稀缺性上,如果任何人都可以任意构造一个比特币,那么比特币就毫无价值,所以比特币的区块链会让参与者完成一项“工作”,根据这个工作的最终结果还分发比特币,这个过程就被叫做“挖矿”。这就类似于一个黄金矿工花一些时间来工作,然后获得一点黄金。



挖矿的原理


如果你百度/谷歌搜索 比特币挖矿的原理 的话,都会给你说是计算一个复杂的数学问题而已,但是这么说的话太笼统而且也太简单。采矿引擎如何工作这是一个重要的知识点,所以我们需要了解一些密码学知识和哈希算法相关的知识,才能知道挖矿的基本原理。



希/散列介绍


单向加密人类能够理解的输入,例如 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 newnewBlock = new Block() 
  { 
    Index = oldBlock.Index + 1, 
    TimeStamp = CalculateCurrentTimeUTC(), 
    BPMBPM = BPM, 
    PrevHash = oldBlock.Hash, 
    DifficultyDifficulty = 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; 
}


效果


扣丁学堂区块链在线学习


想要了解更多内容的小伙伴可以登录扣丁学堂官网咨询。想要学好区块链开发小编给大家推荐口碑良好的扣丁学堂,扣丁学堂有专业老师制定的区块链学习路线图辅助学员学习,此外还有与时俱进的区块链课程体系和区块链视频教程供大家学习,想要学好区块链开发技术的小伙伴快快行动吧。扣丁学堂区块链交流群:850351616。


                          【扫码进入HTML5VIP免费公开课】  


     【关注微信公众号获取更多学习资料】        【扫码进入HTML5前端开发VIP免费公开课】  



查看更多关于“区块链培训技术资讯”的相关文章>>

标签: 区块链培训 区块链技术 区块链开发 区块链视频教程 比特币 以太坊
微信
微博
15311698296

全国免费咨询热线

邮箱:codingke@1000phone.com

官方群:148715490

北京千锋互联科技有限公司版权所有   北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
京ICP备12003911号-6   Copyright © 2013 - 2019
返回顶部 返回顶部