Public Class Block
Public Property Index As Integer ' 区块高度
Public Property PreviousHash As String ' 前一个区块的哈希
Public Property Timestamp As Long ' 时间戳
Public Property Data As String ' 交易数据(简化为字符串)
Public Property Nonce As Long ' 随机数,这是我们主要要找的
Public Property Hash As String ' 本区块的哈希
' 计算区块哈希的函数
Public Function CalculateHash() As String
Dim input As String = String.Format("{0}{1}{2}{3}{4}",
Index,
PreviousHash,
Timestamp,
Data,
Nonce)
Return GetSha256(input)
End Function
End Class
Imports System.Security.Cryptography
Imports System.Text
Public Class HashHelper
Public Shared Function GetSha256(input As String) As String
Using sha256 As SHA256 = SHA256.Create()
Dim bytes As Byte() = sha256.ComputeHash(Encoding.UTF8.GetBytes(input))
Dim builder As New StringBuilder()
For Each b As Byte In bytes
builder.Append(b.ToString("x2"))
Next
Return builder.ToString()
End Using
End Function
End Class
第三步:实现核心的“挖矿”循环
这是挖矿的核心,我们将不断尝试不同的Nonce值,直到找到一个满足条件的哈希。
Public Class Miner
Private _targetPrefix As String ' 目标哈希的前缀,用于控制难度
Private _block As Block
Public Sub New(block As Block, targetPrefix As String)
_block = block
_targetPrefix = targetPrefix
End Sub
Public Sub MineBlock()
Console.WriteLine($"开始挖矿区块 #{_block.Index}...")
Dim stopwatch As Diagnostics.Stopwatch = Diagnostics.Stopwatch.StartNew()
' 循环递增Nonce,直到找到符合条件的哈希
Do While _block.Hash Is Nothing OrElse Not _block.Hash.StartsWith(_targetPrefix)
_block.Nonce += 1
_block.Hash = _block.CalculateHash()
Loop
stopwatch.Stop()
Console.WriteLine($"区块 #{_block.Index] 挖矿成功!")
Console.WriteLine($"找到的Nonce: {_block.Nonce}")
Console.WriteLine($"区块哈希: {_block.Hash}")
Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds} 毫秒")
End Sub
End Class
第四步:主程序入口
我们把这些部分组合起来,模拟一次挖矿过程。
Module Module1
Sub Main()
' 1. 创建一个候选区块
Dim genesisBlock As New Block With {
.Index = 1,
.PreviousHash = "0", ' 创世区块的前哈希为0
.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
.Data = "这是第一个区块,包含一些初始交易。",
.Nonce = 0,
.Hash = ""
}
' 2. 设置挖矿难度
' 难度越高,需要的前导零越多,计算时间越长
' "0000"比"00"难度大得多
Dim difficulty As Integer = 4
Dim targetPrefix As New String("0"c, difficulty)
' 3. 创建矿工并开始挖矿
Dim miner As New Miner(genesisBlock, targetPrefix)
miner.MineBlock()
Console.WriteLine("按任意键退出...")
Console.ReadKey()
End Sub
End Module