区块链模型原理入门学习2——细化模型
以上描述中,存在一些非生产情景的理想化设定。
比如:
1.没有设计谜题难度平衡
2.没有加入加密校验数字签证
3.没有设计个人钱包
4.广播问题
......
代码:
1 using Newtonsoft.Json; 2 using System; 3 using System.Collections.Generic; 4 using System.Diagnostics; 5 using System.Linq; 6 using System.Security.Cryptography; 7 using System.Text; 8 /* 9 ZY的区块链简易模型学习 10 1.1 搭建基础模型(添加数据块、校验数据块) 11 1.2 加入挖矿机制 12 1.3 加入挖矿奖励机制 13 */ 14 namespace TestPrj 15 { 16 class Program 17 { 18 static void Main(string[] args) 19 { 20 Chain chain = new Chain(); 21 22 //1.3 到现在 就不能直接生成块了,而是通过矿工领取待验证块进行计算后验证合法后才能链入区块链上 23 /* Block block1 = new Block("转账10元"); 24 chain.AddNewBlock(block1); 25 Block block2 = new Block("转账30元"); 26 chain.AddNewBlock(block2);*/ 27 28 //1.3 模拟产生两条转账记录 29 var transaction1 = new Transaction("address1", "address2", "30"); 30 var transaction2 = new Transaction("address1", "address2", "15"); 31 32 //1.3 把转账记录加入到转账记录池中 33 chain.AddTransactionToPool(transaction1); 34 chain.AddTransactionToPool(transaction2); 35 36 //1.3 模拟矿工挖矿 37 chain.MineAndReward("addressminer"); 38 39 //查看当前数据链总共数据快数 40 chain.ViewBlockCount(); 41 42 //查看所有数据链 43 chain.ViewAllBlocks(); 44 45 //验证数据链 46 Console.WriteLine(chain.Validate()); 47 48 //模拟篡改数据 49 chain.Blocks[1].Data = "转账100元"; 50 51 //验证数据链 52 Console.WriteLine(chain.Validate()); 53 } 54 } 55 } 56 57 //数据块 58 public class Block 59 { 60 /* //数据 61 private string data;*/ 62 //1.3 这里的data 因为存储的是转账记录 所以类型为object 63 private object data; 64 65 //前一个Block的hash 66 private string prehash; 67 //当前Block的hash 68 private string curhash; 69 private string count; 70 //1.3 确认时间 71 private DateTime time; 72 public Block(object data) 73 { 74 this.prehash = ""; 75 this.data = data; 76 this.curhash = ""; 77 this.count = ""; 78 } 79 80 //注意:这里为了模拟篡改数据专门封装的字段 81 public object Data { get => data; set => data = value; } 82 public string Prehash { get => prehash; set => prehash = value; } 83 public string Curhash { get => curhash; set => curhash = value; } 84 public string Count { get => count; set => count = value; } 85 public DateTime Time { get => time; set => time = value; } 86 87 //计算当前Block的Hash 88 /* public string ComputeHash(string prehash) 89 { 90 this.prehash = prehash; 91 return SHA256(this.data + this.prehash); 92 }*/ 93 94 //1.2 计算当前Block符合要求的Hash 95 public string ComputeBlockPassHash(string prehash, string str = "") 96 { 97 this.prehash = prehash; 98 //return SHA256(this.data + this.prehash + str); 99 //1.3 这里需要返回的数据 100 //更新时间 101 //[转账记录].jsonString+prehash+str 102 this.Time = DateTimeOffset.UtcNow.DateTime; 103 return SHA256(JsonConvert.SerializeObject(this.data) + prehash + str); 104 } 105 106 //Hash256计算 107 public string SHA256(string str) 108 { 109 //如果str有中文,不同Encoding的sha是不同的!! 110 byte[] SHA256Data = Encoding.UTF8.GetBytes(str); 111 112 SHA256Managed Sha256 = new SHA256Managed(); 113 byte[] by = Sha256.ComputeHash(SHA256Data); 114 115 return BitConverter.ToString(by).Replace("-", "").ToLower(); 116 } 117 118 //显示Block数据 119 public void ViewInfo() 120 { 121 Console.WriteLine("===="); 122 Console.WriteLine("[prehash]->" + this.prehash); 123 Console.WriteLine("[data]->"); 124 if (this.data != null) 125 { 126 foreach (var item in (List<Transaction>)this.data) 127 { 128 Console.WriteLine(item.ToString()); 129 } 130 } 131 Console.WriteLine("[time]->" + this.time.ToLocalTime()); 132 Console.WriteLine("[hash]->" + this.curhash); 133 } 134 } 135 136 public class Chain 137 { 138 private List<Block> blocks; 139 140 //1.3 转账记录池,用处存储每一笔转账记录 141 private List<Transaction> transactionPool; 142 143 //1.3 奖励金 144 private string reward = "50"; 145 146 //1.3 困难度 147 private int difficulty = 2; 148 public List<Block> Blocks { get => blocks; set => blocks = value; } 149 150 public Chain() 151 { 152 this.blocks = new List<Block>(); 153 this.transactionPool = new List<Transaction>(); 154 Block genesisBloc = new Block(null); 155 genesisBloc.Curhash = genesisBloc.ComputeBlockPassHash("genesis"); 156 AddNewBlock(genesisBloc); 157 } 158 159 public void ViewBlockCount() 160 { 161 Console.WriteLine("当前数据块总数->" + this.blocks.Count); 162 } 163 164 //添加Block 165 public void AddNewBlock(Block newblock) 166 { 167 //空链的情况 168 if (this.blocks.Count == 0) 169 { 170 this.blocks.Add(newblock); 171 newblock.Curhash = newblock.ComputeBlockPassHash(newblock.Prehash); 172 return; 173 } 174 /*链接新Block*/ 175 //新的Block的prehash是上一个block的curhash 176 newblock.Prehash = this.blocks[this.blocks.Count - 1].Curhash; 177 178 //1.2 加入挖矿计算后,需要符合要求的Hash才能被链入,其中会涉及平均计算时间和设置计算困难度的关系(这里暂时不考虑) 179 //newblock.Curhash = newblock.ComputeHash(newblock.Prehash); 180 181 /*1.2挖矿计算*/ 182 ComputePassHash(newblock, this.difficulty); 183 184 /*添加新Block*/ 185 this.blocks.Add(newblock); 186 } 187 188 //1.2 获取计算难度 189 public string GetComputeDifficulty(int difficulty) 190 { 191 //这里做简单要求,即根据难度,形成指定数量的0的字符串 192 string passStr = ""; 193 for (int setDiffIndex = 0; setDiffIndex < difficulty; setDiffIndex++) 194 { 195 passStr += "0"; 196 } 197 return passStr; 198 } 199 200 //1.2 计算符合要求的哈希值 201 public void ComputePassHash(Block block, int difficulty) 202 { 203 int count = 0; 204 while (true) 205 { 206 count++; 207 //加入参数计算哈希值 208 string checkHash = block.ComputeBlockPassHash(block.Prehash, count.ToString()); 209 Console.WriteLine("第 " + count + "次计算->" + checkHash); 210 //判断计算的哈希值符合相应难度的要求,即前哈希值前四位必须为0才算合格 211 if (checkHash.Substring(0, difficulty).Equals(GetComputeDifficulty(difficulty))) 212 { 213 block.Curhash = checkHash; 214 block.Count = count.ToString(); 215 break; 216 } 217 } 218 //模拟挖掘到符合的哈希值 219 Console.WriteLine("经过" + count + "次计算挖掘到->" + block.Curhash); 220 221 //1.3清空转账记录池 222 //这里屏蔽掉的原因:因为本次学习取到了转账记录池里的全部记录的缘故,清理后会影响后面的显示,好吧..我承认,这就是个小BUG... 223 //this.transactionPool.Clear(); 224 } 225 226 //查看所有Block 227 public void ViewAllBlocks() 228 { 229 foreach (var item in this.blocks) 230 { 231 item.ViewInfo(); 232 } 233 } 234 235 //验证Chain 236 public bool Validate() 237 { 238 //无任何数据块的情况 239 if (this.blocks.Count == 0) 240 { 241 Console.WriteLine("[数据链异常]->数据链为空!"); 242 return false; 243 } 244 //只有源数据块的情况 245 else if (this.blocks.Count == 1) 246 { 247 Console.WriteLine("验证完毕!"); 248 return true; 249 } 250 251 //遍历校验标志 252 bool checkBlockSign = true; 253 254 //遍历检查数据块,因为不检查源数据块,下标从1开始 255 for (int checkBlockIndex = 1; checkBlockIndex < this.blocks.Count; checkBlockIndex++) 256 { 257 //检验curhash 258 var checkBlock = this.blocks[checkBlockIndex]; 259 if (checkBlock.Curhash != checkBlock.ComputeBlockPassHash(checkBlock.Prehash, checkBlock.Count)) 260 { 261 Console.WriteLine("[数据被篡改]->" + checkBlockIndex); 262 checkBlockSign = false; 263 break; 264 } 265 /* //验证prehash 266 if (checkBlock.Prehash != this.blocks[checkBlockIndex - 1].Curhash) 267 { 268 Console.WriteLine("[数据链断裂]->" + checkBlockIndex); 269 checkBlockSign = false; 270 break; 271 }*/ 272 } 273 Console.WriteLine("验证完毕!"); 274 return checkBlockSign; 275 } 276 277 //1.3 添加转账记录 278 public void AddTransactionToPool(Transaction transaction) 279 { 280 this.transactionPool.Add(transaction); 281 } 282 283 //1.3挖矿并获取奖励 284 public void MineAndReward(string minerAddress) 285 { 286 //生成奖励转账 因为系统奖励,所以转账人地址是空的 287 var rewardTransform = new Transaction("", minerAddress, this.reward); 288 289 //把矿工的奖励转账记录也要存进转账池子里 290 this.transactionPool.Add(rewardTransform); 291 292 //生成block(这里默认h获取转账池里的所有转账记录) 293 var block = new Block(this.transactionPool); 294 295 //计算合法哈希值 296 AddNewBlock(block); 297 } 298 } 299 300 //1.3交易记录 转账人 收款人 转账数额 (注意!这里没有转账时间,根据中本聪的论文,转账时间和block生成的时间是统一的,也就是说block被挖到的时候才会创建时间) 301 public class Transaction 302 { 303 //转账方地址 304 public string transferor; 305 //收款方地址 306 public string payee; 307 //转账金额 308 public string money; 309 310 public Transaction(string transferor, string payee, string money) 311 { 312 this.transferor = transferor; 313 this.payee = payee; 314 this.money = money; 315 } 316 public override string ToString() 317 { 318 return this.transferor + "-" + this.payee + "-" + this.money; 319 } 320 }
执行结果:
到此,奖励机制加入完成了,当然,还有很多地方需要优化和改进。
【学习是人类进步的阶梯】
【敬畏能量 敬畏自然】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2020-02-23 模拟射击文字类游戏(Python)
2020-02-23 模拟射击文字类游戏