参考文章:http://www.cnblogs.com/myzony/p/8478789.html
使用 C# + Asp.Net Core 实现自己的区块链项目。
首先新建一个 Asp.Net Core 项目,然后选择 Empty Project(空项目) 类型,建立完成后无需进行任何配置。(本文以Microsoft Visual Studio2017企业版创建项目)
过程如下:
(1).打开文件→新建→项目
(2) 选择Visual C# 菜单栏下的Web →选择.NET.Core→选择ASP.NET.Core Web应用程序进行创建项目。
(3)选择空类型进行创建,勾选:为HTPS配置,创建完成后不需要进行任何配置。
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;
代码如下:
public struct Block
{
///
/// 区块位置
///
public int Index { get; set; }
///
/// 区块生成时间戳
///
public string TimeStamp { get; set; }
///
/// 心率数值
///
public int BPM { get; set; }
///
/// 区块 SHA-256 散列值
///
public string Hash { get; set; }
///
/// 前一个区块 SHA-256 散列值
///
public string PrevHash { get; set; }
}
代码如下:
public static class BlockGenerator
{
public static List
internal static string CalculateCurrentTimeUTC()
{
throw new NotImplementedException();
}
internal static void SwitchChain(List
{
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();
}
}
代码如下:
///
/// 计算区块 HASH 值
///
/// 区块实例
///
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();
}
代码如下:
///
/// 生成新的区块
///
/// 旧的区块数据
/// 心率
///
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;
}
///
/// 计算当前时间的 UTC 表示格式
///
///
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();
}
///
/// 检验区块是否有效
///
/// 新生成的区块数据
/// 旧的区块数据
///
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;
}
///
/// 如果新的区块链比当前区块链更新,则切换当前区块链为最新区块链
///
/// 新的区块链
public static void SwitchChain(List
{
if (newBlockChain.Count > _blockChain.Count)
{
_blockChain = newBlockChain;
}
}
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
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));
});
});
}
}
}
(1)先通过PostMan创建一个创世块
PostMan下载链接:https://www.getpostman.com/products,选择适用版本安装后创建一个创世块。
(2)然后尝试多添加几个之后,访问 BlockChain 来查看已经存在的区块链结构。
附c#项目代码:
https://gitee.com/DiJun1/QuKuaiLianShiLi