.Net Core搭建区块链,实现比特币流转逻辑
缘起
一直对区块链很感兴趣,但是又感觉一头雾水,这两天特地研究了下比特币的底层逻辑,豁然开朗。
区块链
区块链其实没那么复杂,其实就是一种链表存储结构,该链表的最小单位是区块
区块主要包含区块高度、上个区块Hash值、区块存储数据、区块创建时间、区块Hash值、随机数
Hash值是通过一定算法,对当前区块其他属性值进行签名得到
区块之间首尾相连,当前区块会存储上个区块的Hash值,同时当前区块的Hash值的计算依赖上个区块的Hash值,因此,最终形成的区块链将变得非常敏感,但凡有一个区块的数据被篡改,后面区块的Hash值将不符合链表规则,无法校验通过,因此可以大幅提升数据的可信度。
去中心化
区块链技术中,去中心化也是一个重要概念,每个拥有某个区块链的用户,都将持续化存储该区块链全部信息到本地,也即每个用户都拥有完整的区块链数据库。
项目
项目地址
https://github.com/Rhyheart/drea-block-chain
区块实体
public class Block { public Block(long index, string previousHash, List<Record> data) { Index = index; PreviousHash = previousHash; Data = data; TimeStamp = DateTime.Now; Nonce = Guid.NewGuid().ToString("N"); Hash = CalculateHash(); } /// <summary> /// 索引,区块高度 /// </summary> public long Index { get; set; } /// <summary> /// 上个区块Hash值 /// </summary> public string PreviousHash { get; set; } /// <summary> /// 当前区块存储的数据 /// </summary> public List<Record> Data { get; set; } /// <summary> /// 区块创建时间 /// </summary> public DateTime TimeStamp { get; set; } /// <summary> /// 随机数,用于改变Hash值,让其符合创世人设定的规则 /// </summary> public string Nonce { get; set; } /// <summary> /// 当前区块Hash值 /// </summary> public string Hash { get; set; } /// <summary> /// 计算Hash值 /// </summary> /// <returns></returns> public string CalculateHash() { var sha256 = SHA256.Create(); var inputBytes = Encoding.ASCII.GetBytes($"{PreviousHash}-{Data}-{TimeStamp}-{Nonce}"); var outputBytes = sha256.ComputeHash(inputBytes); return Convert.ToBase64String(outputBytes); } }
数据实体
public class Record { /// <summary> /// 转账人 /// </summary> public string Sender { get; set; } /// <summary> /// 收账人 /// </summary> public string Receiver { get; set; } /// <summary> /// 金额 /// </summary> public decimal Amount { get; set; } }
链服务
public class BlockChainService { public IList<Block> Chain { set; get; } public BlockChainService() { InitializeChain(); } /// <summary> /// 初始化区块链 /// </summary> public void InitializeChain() { Chain = new List<Block>(); } /// <summary> /// 添加创世区块 /// </summary> /// <param name="records"></param> public void AddGenesisBlock(List<Record> records) { Chain.Add(new Block(0, "", records)); } /// <summary> /// 获取最新区块 /// </summary> /// <returns></returns> public Block GetLatestBlock() { return Chain.Last(); } /// <summary> /// 添加区块 /// </summary> /// <param name="records"></param> public void AddBlock(List<Record> records) { var latestBlock = GetLatestBlock(); Chain.Add(new Block(latestBlock.Index + 1, latestBlock.Hash, records)); } /// <summary> /// 验证当前区块链数据是否合规 /// </summary> /// <returns></returns> public bool IsValid() { if (Chain[0].Hash != Chain[0].CalculateHash()) { return false; } for (var i = 1; i < Chain.Count; i++) { var currentBlock = Chain[i]; var previousBlock = Chain[i - 1]; if (currentBlock.Hash != currentBlock.CalculateHash()) { return false; } if (currentBlock.PreviousHash != previousBlock.Hash) { return false; } } return true; } }
入口方法
using Drea.BlockChain; using Newtonsoft.Json; var blockChainService = new BlockChainService(); #region 创世区块 Console.WriteLine("创世人 Rhyheart 创建了区块链,开始添加创世区块..."); var records = new List<Record> { new Record { Sender = "System", Receiver = "Rhyheart", Amount = 50 } }; blockChainService.AddGenesisBlock(records); Console.WriteLine("创世区块添加成功,创世人 Rhyheart 获得系统奖励的 50 个虚拟货币"); Console.WriteLine(); #endregion #region 第二区块 Console.WriteLine("交易进行中..."); var records2 = new List<Record> { new Record { Sender = "Rhyheart", Receiver = "Mark", Amount = 5 }, new Record { Sender = "Rhyheart", Receiver = "Frank", Amount = 5 }, new Record { Sender = "Rhyheart", Receiver = "Mark", Amount = 10 }, new Record { Sender = "Rhyheart", Receiver = "Jack", Amount = 5 }, new Record { Sender = "Mark", Receiver = "Rhyheart", Amount = 5 } }; Console.WriteLine("产生了 5 笔新交易,符合区块打包规则,用户们开始争夺第二区块添加权..."); Console.WriteLine("用户 Frank 争夺成功,获得区块添加权,开始添加第二区块..."); blockChainService.AddBlock(records2); Console.WriteLine("第二区块添加成功,用户 Frank 获得系统奖励的 50 个虚拟货币"); Console.WriteLine(); #endregion #region 第三区块 Console.WriteLine("交易进行中..."); var records3 = new List<Record> { new Record { Sender = "System", Receiver = "Frank", Amount = 50 }, new Record { Sender = "Frank", Receiver = "Mark", Amount = 5 }, new Record { Sender = "Mark", Receiver = "Frank", Amount = 5 }, new Record { Sender = "Frank", Receiver = "Mark", Amount = 10 }, new Record { Sender = "Frank", Receiver = "Jack", Amount = 5 }, new Record { Sender = "Mark", Receiver = "Rhyheart", Amount = 5 } }; Console.WriteLine("产生了 5 笔新交易,符合区块打包规则,用户们开始争夺第三区块添加权..."); Console.WriteLine("用户 Mark 争夺成功,获得区块添加权,开始添加第三区块..."); blockChainService.AddBlock(records3); Console.WriteLine("第二区块添加成功,用户 Mark 获得系统奖励的 50 个虚拟货币"); Console.WriteLine(); #endregion Console.WriteLine($"区块链数据验证:{blockChainService.IsValid()}"); Console.WriteLine(); var totalAmount = blockChainService.Chain.Sum(x => x.Data.Where(x => x.Sender == "System").Sum(y => y.Amount)); Console.WriteLine($"区块链总虚拟货币数:{totalAmount}"); Console.WriteLine(); var receiveAmount = blockChainService.Chain.Sum(x => x.Data.Where(x => x.Receiver == "Rhyheart").Sum(y => y.Amount)); var sendAmount = blockChainService.Chain.Sum(x => x.Data.Where(x => x.Sender == "Rhyheart").Sum(y => y.Amount)); var amount = receiveAmount - sendAmount; Console.WriteLine($"区块链 Rhyheart 用户虚拟货币余额:{amount}"); Console.WriteLine(); var chain = JsonConvert.SerializeObject(blockChainService.Chain); Console.WriteLine($"区块链详情:{chain}"); Console.WriteLine();