参考文章: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#完整源码即运行截图)相关推荐

  1. php区块链以太坊,兄弟连区块链教程以太坊源码分析CMD深入分析(一)

    兄弟连区块链教程以太坊源码分析CMD深入分析. cmd包分析 cmd下面总共有13个子包,除了util包之外,每个子包都有一个主函数,每个主函数的init方法中都定义了该主函数支持的命令,如 geth ...

  2. 区块链开源项目Asch源码初探

    Asch这个名字是 App Side Chain 的缩写. 是一种基于区块链跨链技术的应用开发平台,目前全部核心代码已经在GitHub上开源. 区块链是比特币的底层技术,但是名气低于比特币,但是个人认 ...

  3. 机器人编程python代码_自己动手开发智能聊天机器人完全指南(附python完整源码)...

    一.前言 人工智能时代,开发一款自己的智能问答机器人,一方面提升自己的AI能力,另一方面作为转型AI的实战练习.在此把学习过程记录下来,算是自己的笔记. 二.正文 2.1 下载pyaiml 下载pya ...

  4. 自己动手开发智能聊天机器人完全指南(附python完整源码)

    一.前言 人工智能时代,开发一款自己的智能问答机器人,一方面提升自己的AI能力,另一方面作为转型AI的实战练习.在此把学习过程记录下来,算是自己的笔记. 二.正文 2.1 下载pyaiml 下载pya ...

  5. 中国 国外 现有主流区块链平台 有哪些 源码 文档 总结

    一.国内 微众银行( FISCO BCOS ) 文档: FISCO BCOS 技术文档 - FISCO BCOS v2.9.0 文档https://fisco-bcos-documentation.r ...

  6. SpringCloud企业分布式微服务云架构快速开发平台源码之运行截图

    鸿鹄云架构系统管理平台是一个大型企业.分布式.微服务.云架构的JavaEE体系快速研发平台,基于模块化.微服务化.原子化.热部署的设计思想,使用成熟领先的无商业限制的主流开源技术(Spring Clo ...

  7. Python不能做游戏?游戏实战之-----《ink spill》(附游戏完整源码)

    嗨喽-小伙伴们,大家早上好,中午好,晚上好呀, 通过前两章对Pygame的学习,我们了解了它的基本使用,附上链接: 1. Python不能做游戏?一小时做出一个游戏! 2. Python不能做游戏?P ...

  8. 最新接单抢单系统返利+资金盘+区块链自动抢单系统源码

    正文: 程序仅供学习研究,下方是程序完整标题: 暂时没找到系统的介绍啥的. 程序: wwefu.lanzouv.com/i6R3x068kg6h 图片:

  9. java 制作动态手机壁纸_android 动态切换壁纸实例 利用service机制实现 附完整源码 带动态截图...

    [实例简介]通过点击 startService实现 android手机动态壁纸功能 [实例截图] [核心代码] main.xml android:orientation="vertical& ...

最新文章

  1. oracle简写sql,Oracle通过sqlplus编辑sql命令
  2. 入门Java要学习的一些基本和高级工具
  3. 【数据结构与算法】之深入解析“合并两个有序链表”的求解思路与算法示例
  4. python getostime_Python os.getrandom()用法及代码示例
  5. 用aspnet_compiler发布网站 (转载:My way of my life )
  6. 支付宝用大数据憋死伪基站骗子
  7. Jeecg-Boot上传及下载附件异常处理
  8. 系统封装接口层 cmsis_os
  9. CTA策略02_boll
  10. mysql union (all) 后order by的排序失效问题解决
  11. SpringBoot+zk+dubbo架构实践(四):sb+zk+dubbo框架搭建(内附源码GitHub地址)
  12. udhcpc 移植和使用
  13. uint8_t范围_uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结
  14. OpenCV - SIFT-SURF(Python实现)
  15. 大疆网上测评题库_大疆笔试题
  16. RNN神经网络模型综述
  17. 搜索优化—如何在Google搜索引擎上排名靠前Google左侧排名
  18. Win7补丁对比环境搭建
  19. IE浏览器卡死提示是否停止运行此脚本的解决办法
  20. bone。animation

热门文章

  1. 医疗机器人的现状和未来:探讨未来机器人在医疗保健中的应用
  2. 控制网络技术(英文一)
  3. jvm调优-hprof 文件打开
  4. 01-10-Hadoop-HA-概述
  5. c#版本视频在线播放(通用播放器调用),支持avi,wmv,asf,mov,rm,ra,ram等
  6. 2019第二届北京国际新零售及无人售货展览会
  7. 从行业实践中来:华为的智能制造“懂行人”炼成记
  8. 银联商户号变更及证书更新
  9. ElasticSearch 亿级数据检索深度性能优化
  10. Xcode代码中特殊的注释技术——TODO、FIXME和XXX的用法