C# 实现区块链(附c#完整源码即运行截图)
参考文章:http://www.cnblogs.com/myzony/p/8478789.html
使用 C# + Asp.Net Core 实现自己的区块链项目。
1.项目配置
首先新建一个 Asp.Net Core 项目,然后选择 Empty Project(空项目) 类型,建立完成后无需进行任何配置。(本文以Microsoft Visual Studio2017企业版创建项目)
过程如下:
(1).打开文件→新建→项目
(2) 选择Visual C# 菜单栏下的Web →选择.NET.Core→选择ASP.NET.Core Web应用程序进行创建项目。
(3)选择空类型进行创建,勾选:为HTPS配置,创建完成后不需要进行任何配置。
2.Program.cs中需要的引用声明
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
3.建立区块链数据模型
(1)创建一个具体的区块数据模型,使用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; }
}
(2)之后我们新建一个 BlockGenerator 静态类用于管理区块链,并且使用一个 List 保存区块链数据。
代码如下:
public static class BlockGenerator
{
public static List<Block> _blockChain = new List<Block>();
internal static string CalculateCurrentTimeUTC()
{
throw new NotImplementedException();
}
internal static void SwitchChain(List<Block> newBlockChain)
{
throw new NotImplementedException();
}
internal static Block GenerateBlock(Block oldBlock, int bpm)
{
throw new NotImplementedException();
}
internal static bool IsBlockValid(Block newBlock, Block oldBlock)
{
throw new NotImplementedException();
}
}
(3)在 BlockGenerator 当中添加一个函数用于计算 Block 的 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}";
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();
}
(4)这里的 CalculateHash 函数接收一个 Block 实例,通过该实例当中的 Index、TimeStamp、BPM、PrevHash 的值来计算出当前块的 SHA256 Hash 值,之后我们就可以来编写一个生成块的函数:
代码如下:
/// <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
};
newBlock.Hash = CalculateHash(newBlock);
return newBlock;
}
(5)这个函数需要接收前一个块对象的值,用于新区块的 Index 递增以及 新的 SHA256 Hash 计算。
这里掺入了一个 CalculateCurrentTimeUTC 函数,该函数主要是用于将 DateTime.Now 时间转换为 UTC 时间,如下:
/// <summary>
/// 计算当前时间的 UTC 表示格式
/// </summary>
/// <returns>UTC 时间字符串</returns>
public static string CalculateCurrentTimeUTC()
{
DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
DateTime nowTime = DateTime.Now;
long unixTime = (long)Math.Round((nowTime - startTime).TotalMilliseconds, MidpointRounding.AwayFromZero);
return unixTime.ToString();
}
(6)每一个区块都是不可信的,所以我们需要在生成新的区块的时候对其进行校验,校验规则如下:
- 校验新区块与旧区块的 Index 是否正确递增
- 校验新区块的 Hash 值是否正确
- 校验新区块的 PrevHash 值是否与旧区块的 Hash 值匹配
有了上述几种条件,我们可以编写一个校验函数如下:
/// <summary>
/// 检验区块是否有效
/// </summary>
/// <param name="newBlock">新生成的区块数据</param>
/// <param name="oldBlock">旧的区块数据</param>
/// <returns>有效返回 TRUE,无效返回 FALSE</returns>
public static bool IsBlockValid(Block newBlock, Block oldBlock)
{
if (oldBlock.Index + 1 != newBlock.Index) return false;
if (oldBlock.Hash != newBlock.PrevHash) return false;
if (CalculateHash(newBlock) != newBlock.Hash) return false;
return true;
}
(7)除开区块校验的问题之外,如果有两个节点被分别添加到各自的区块链上,我们应该始终以最长的那一条为主线,因为最长的那一条意味着他的区块数据始终是最新的。所以,我们还需要一个更新最新区块的函数(之前有声明)。
/// <summary>
/// 如果新的区块链比当前区块链更新,则切换当前区块链为最新区块链
/// </summary>
/// <param name="newBlockChain">新的区块链</param>
public static void SwitchChain(List<Block> newBlockChain)
{
if (newBlockChain.Count > _blockChain.Count)
{
_blockChain = newBlockChain;
}
}
3.集成到Web
在StartUp 当中,添加两个新的路由
Startup.cs源码如下(包含引用及路由)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using static WebApplication1.Program;
namespace WebApplication1
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Map("/BlockChain", _ =>
{
_.Run(async context =>
{
if (context.Request.Method == "POST")
{
// 增加区块链
if (BlockGenerator._blockChain.Count == 0)
{
Block firstBlock = new Block()
{
Index = 0,
TimeStamp = BlockGenerator.CalculateCurrentTimeUTC(),
BPM = 0,
Hash = string.Empty,
PrevHash = string.Empty
};
BlockGenerator._blockChain.Add(firstBlock);
await context.Response.WriteAsync(JsonConvert.SerializeObject(firstBlock));
}
else
{
var form = await context.Request.ReadFormAsync();
int.TryParse(form["BPM"][0], out int bpm);
Block oldBlock = BlockGenerator._blockChain.Last();
Block newBlock = BlockGenerator.GenerateBlock(oldBlock, bpm);
if (BlockGenerator.IsBlockValid(newBlock, oldBlock))
{
List<Block> newBlockChain = new List<Block>();
foreach (var block in BlockGenerator._blockChain)
{
newBlockChain.Add(block);
}
newBlockChain.Add(newBlock);
BlockGenerator.SwitchChain(newBlockChain);
}
await context.Response.WriteAsync(JsonConvert.SerializeObject(newBlock));
}
}
});
});
app.Map("/BlockChains", _ =>
{
_.Run(async context =>
{
await context.Response.WriteAsync(JsonConvert.SerializeObject(BlockGenerator._blockChain));
});
});
}
}
}
4.暂行调试结果:
5.最终效果
(1)先通过PostMan创建一个创世块
PostMan下载链接:https://www.getpostman.com/products,选择适用版本安装后创建一个创世块。
(2)然后尝试多添加几个之后,访问 BlockChain 来查看已经存在的区块链结构。
附c#项目代码:
https://gitee.com/DiJun1/QuKuaiLianShiLi
C# 实现区块链(附c#完整源码即运行截图)相关推荐
- php区块链以太坊,兄弟连区块链教程以太坊源码分析CMD深入分析(一)
兄弟连区块链教程以太坊源码分析CMD深入分析. cmd包分析 cmd下面总共有13个子包,除了util包之外,每个子包都有一个主函数,每个主函数的init方法中都定义了该主函数支持的命令,如 geth ...
- 区块链开源项目Asch源码初探
Asch这个名字是 App Side Chain 的缩写. 是一种基于区块链跨链技术的应用开发平台,目前全部核心代码已经在GitHub上开源. 区块链是比特币的底层技术,但是名气低于比特币,但是个人认 ...
- 机器人编程python代码_自己动手开发智能聊天机器人完全指南(附python完整源码)...
一.前言 人工智能时代,开发一款自己的智能问答机器人,一方面提升自己的AI能力,另一方面作为转型AI的实战练习.在此把学习过程记录下来,算是自己的笔记. 二.正文 2.1 下载pyaiml 下载pya ...
- 自己动手开发智能聊天机器人完全指南(附python完整源码)
一.前言 人工智能时代,开发一款自己的智能问答机器人,一方面提升自己的AI能力,另一方面作为转型AI的实战练习.在此把学习过程记录下来,算是自己的笔记. 二.正文 2.1 下载pyaiml 下载pya ...
- 中国 国外 现有主流区块链平台 有哪些 源码 文档 总结
一.国内 微众银行( FISCO BCOS ) 文档: FISCO BCOS 技术文档 - FISCO BCOS v2.9.0 文档https://fisco-bcos-documentation.r ...
- SpringCloud企业分布式微服务云架构快速开发平台源码之运行截图
鸿鹄云架构系统管理平台是一个大型企业.分布式.微服务.云架构的JavaEE体系快速研发平台,基于模块化.微服务化.原子化.热部署的设计思想,使用成熟领先的无商业限制的主流开源技术(Spring Clo ...
- Python不能做游戏?游戏实战之-----《ink spill》(附游戏完整源码)
嗨喽-小伙伴们,大家早上好,中午好,晚上好呀, 通过前两章对Pygame的学习,我们了解了它的基本使用,附上链接: 1. Python不能做游戏?一小时做出一个游戏! 2. Python不能做游戏?P ...
- 最新接单抢单系统返利+资金盘+区块链自动抢单系统源码
正文: 程序仅供学习研究,下方是程序完整标题: 暂时没找到系统的介绍啥的. 程序: wwefu.lanzouv.com/i6R3x068kg6h 图片:
- java 制作动态手机壁纸_android 动态切换壁纸实例 利用service机制实现 附完整源码 带动态截图...
[实例简介]通过点击 startService实现 android手机动态壁纸功能 [实例截图] [核心代码] main.xml android:orientation="vertical& ...
最新文章
- oracle简写sql,Oracle通过sqlplus编辑sql命令
- 入门Java要学习的一些基本和高级工具
- 【数据结构与算法】之深入解析“合并两个有序链表”的求解思路与算法示例
- python getostime_Python os.getrandom()用法及代码示例
- 用aspnet_compiler发布网站 (转载:My way of my life )
- 支付宝用大数据憋死伪基站骗子
- Jeecg-Boot上传及下载附件异常处理
- 系统封装接口层 cmsis_os
- CTA策略02_boll
- mysql union (all) 后order by的排序失效问题解决
- SpringBoot+zk+dubbo架构实践(四):sb+zk+dubbo框架搭建(内附源码GitHub地址)
- udhcpc 移植和使用
- uint8_t范围_uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结
- OpenCV - SIFT-SURF(Python实现)
- 大疆网上测评题库_大疆笔试题
- RNN神经网络模型综述
- 搜索优化—如何在Google搜索引擎上排名靠前Google左侧排名
- Win7补丁对比环境搭建
- IE浏览器卡死提示是否停止运行此脚本的解决办法
- bone。animation
热门文章
- 医疗机器人的现状和未来:探讨未来机器人在医疗保健中的应用
- 控制网络技术(英文一)
- jvm调优-hprof 文件打开
- 01-10-Hadoop-HA-概述
- c#版本视频在线播放(通用播放器调用),支持avi,wmv,asf,mov,rm,ra,ram等
- 2019第二届北京国际新零售及无人售货展览会
- 从行业实践中来:华为的智能制造“懂行人”炼成记
- 银联商户号变更及证书更新
- ElasticSearch 亿级数据检索深度性能优化
- Xcode代码中特殊的注释技术——TODO、FIXME和XXX的用法