区块链:
区块链是一个
信息技术领域的术语。从本质上讲,它是一个共享
数据库,存储于其中的数据或信息,具有“不可伪造”“全程留痕”“可以追溯”“公开透明”“集体维护”等特征。基于这些特征,
区块链技术奠定了坚实的“信任“基础,创造了可靠的“合作”机制,具有广阔的运用前景。
2019年1月10日,国家互联网信息办公室发布《
区块链信息服务管理规定》
[1] 。2019年10月24日,在中央政治局第十八次集体学习时,总书记强调,“把区块链作为核心技术自主创新的重要突破口”“加快推动区块链技术和产业创新发展”。“区块链”已走进大众视野,成为社会的关注焦点。 (百度百科)
关键字: 共享数据库、术语
特征:“不可伪造”“全程留痕”“可以追溯”“公开透明”“集体维护”
奠定:“信任“、 创造 “合作”
现在主要应用到: 产品溯源、信用合约、“比特币”发币;
c# 开发一个简单的区块链demo
1、定义结构:
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; } }
2、定义操作类 :生成 校验都在这边
public static class BlockGenerator { public static List<Block> _blockChain = new List<Block>(); public static int _difficulty; /// <summary> /// 计算区块 HASH 值 比特币是采用double 的sha256. 我们这边采用以单层 /// </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}"; //$"{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(); } /// <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 = oldBlock.Difficulty }; _difficulty = oldBlock.Difficulty;// // 挖矿 ing... for (int i = 0; ; i++) { newBlock.Nonce = i.ToString("x2"); if (!IsHashValid(CalculateHash(newBlock), oldBlock.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; } /// <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(); } /// <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; } /// <summary> /// 如果新的区块链比当前区块链更新,则切换当前区块链为最新区块链 /// </summary> /// <param name="newBlockChain">新的区块链</param> public static void SwitchChain(List<Block> newBlockChain) { if (newBlockChain.Count > _blockChain.Count) { _blockChain = newBlockChain; } } /// <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; } }
3、应用: staup.cs 里面添加路由
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, Difficulty=1 }; BlockGenerator._blockChain.Add(firstBlock); await context.Response.WriteAsync(JsonConvert.SerializeObject(firstBlock)); } else { // int.TryParse(context.Request.Form["BPM"][0], out int bpm); 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)); } else { await context.Response.WriteAsync(JsonConvert.SerializeObject(new { msg="无效的区块链"})); } } } }); }); app.Map("/BlockChains", _ => { _.Run(async context => { await context.Response.WriteAsync(JsonConvert.SerializeObject(BlockGenerator._blockChain)); }); });
4、验证 测试 使用postman ,记得第二次请求一定要提交一个BPM 的参数 也可以自己修改程序 自动生成
5、大家有疑问可以相互讨论下;
看图: 有些难度小的一下子就计算出来,如果难度大的就要继续计算;