C# 比特币哈希算法

C# 比特币哈希算法,c#,sha256,C#,Sha256,一、 就像网络世界中许多绝望的浪漫主义者一样,我相信我可以成功地挖掘比特币。问题是,我无法获得从上一个矿块获取数据并为下一个矿块创建哈希的基本算法。我从几篇文章中了解到,我们从块的当前哈希开始,反转并附加merkel根,添加nonce,然后得到该字符串的SHA256哈希 static void Main(string[] args) { //get the hash of the current block string currentHash

一、 就像网络世界中许多绝望的浪漫主义者一样,我相信我可以成功地挖掘比特币。问题是,我无法获得从上一个矿块获取数据并为下一个矿块创建哈希的基本算法。我从几篇文章中了解到,我们从块的当前哈希开始,反转并附加merkel根,添加nonce,然后得到该字符串的SHA256哈希

     static void Main(string[] args)
    {

        //get the hash of the current block
        string currentHash = 
        @"000000000000000000c5c04011f9a3fb5f46064fed7e06dcdae69024ed6484c1";

        //get the merkel root
        string merkel = 
        @"f73a382814c51cbc5a59ab9817ac54c63decb7b3dac5b049df5213c029162bdf";

        //reverese the merkel root
        char[] c = merkel.ToCharArray();
        Array.Reverse(c);
        merkel = new string(c);

        //get a hash object that returns SHA256
        Hash hash = new Hash();

        //get the nonce that mined the block
        uint nonce = 3546041956;

        //string together current hash, merkel root and the hex of the nonce
        string stringTotal = currentHash + merkel + nonce.ToString("x2");

        //calculate the SHA256 hash of the 
        string nextHash = hash.GetHash(stringTotal);

        Console.WriteLine(nextHash);

        Console.ReadKey();
    }

有人知道正确的算法吗?我使用这个块并试图计算下一个块的哈希值。

所以我对同样的事情很好奇。这就是我想到的。这显然不是产品质量问题,但它能让人理解这个想法,而且似乎很管用

如果没有反向和交换逻辑,这可能会容易得多,因为我所寻找的一切实际上都没有文档记录

无论如何,希望这有帮助。如果您感兴趣,我在这里找到了很多帮助:

类程序
{
静态void Main(字符串[]参数)
{
// https://blockchain.info/block-height/286819
int版本=2;
字符串previousBlock=“000000000000000 117C80378B8DA0E33559B5997F2AD55E2F7D18EC1975B9717”;
字符串merkelRoot=“871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a”;
uint nonce=856192328;
long timestamp=new DateTimeOffset(DateTime.SpecifyKind(DateTime.Parse(“2014-02-20 04:57:25”),DateTimeKind.Utc)).ToUnixTimeSeconds();
uint位=419520339;
var header=新的StringBuilder()
.Append(ReverseAndSwap(version.ToString(“D8”))
.Append(ReverseAndSwap(previousBlock))
.Append(ReverseAndSwap(merkelRoot))
.Append(ReverseAndSwap(timestamp.ToString(“x2”))
.Append(ReverseAndSwap(bits.ToString(“x2”))
.Append(ReverseAndSwap(nonce.ToString(“x2”))
.ToString();
Debug.Assert(string.CompareOrdinal(头,“02000000017975B97C18ED1F7E255ADF297599B55330EDAB87803C81701000000008A97295A2747B4F1A0B3948DF3990344C0E19FA6B2B92B3A19C8E6BADC141787358B05535F011948750833”)=0;
var字节=十六字节(标头);
SHA256 sha=新的SHA256Managed();
bytes=sha.ComputeHash(sha.ComputeHash(bytes)).Reverse().ToArray();
var hash=BytesToHex(字节);
Assert(string.CompareOrdinal(散列,“0000000000000000 E067A478024AddFecd93628978AA52D91Fabd42982A50”)==0;
}
专用静态字符串反向EANDSWAP(字符串输入)
{
StringBuilder sb=新的StringBuilder();
对于(var i=input.Length-1;i>=0;i--)
{
sb.Append(输入[i-(i%2==0-1:1)];
}
使某人返回字符串();
}
公共静态字节[]十六进制字节(字符串十六进制)
{
字节[]十六字节=新字节[hex.Length/2];
for(int index=0;index
哈希只能在一堆字节上进行。在讨论哈希时,您将看到的任何字符串都只是字节的表示形式。哈希对象接收字符串,转换为字节,应用SHA256算法,然后将字节[]中的每个字节附加到带有(“x2”)的StringBuilder对象。public string GetHash(string input){string Hash=“”;byte[]b=Encoding.UTF8.GetBytes(输入);HashAlgorithm ha=new SHA256CryptoServiceProvider();byte[]b2=ha.ComputeHash(b);StringBuilder=new StringBuilder();foreach(b2中的字节i){builder.Append(i.ToString(“x2”);}hash=builder.ToString();return hash;}反转merkel根-我不敢相信你必须反转字节表示的字符(2个字符代表1个字节)将十六进制字符串表示解码为字节数组,然后只反转该字节数组。散列时远离字符串,只使用流或字节数组。
class Program
{
    static void Main(string[] args)
    {
        // https://blockchain.info/block-height/286819
        int version = 2;
        string previousBlock = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717";
        string merkelRoot = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a";
        uint nonce = 856192328;
        long timestamp = new DateTimeOffset(DateTime.SpecifyKind(DateTime.Parse("2014-02-20 04:57:25"), DateTimeKind.Utc)).ToUnixTimeSeconds();
        uint bits = 419520339;

        var header = new StringBuilder()
            .Append(ReverseAndSwap(version.ToString("D8")))
            .Append(ReverseAndSwap(previousBlock))
            .Append(ReverseAndSwap(merkelRoot))
            .Append(ReverseAndSwap(timestamp.ToString("x2")))
            .Append(ReverseAndSwap(bits.ToString("x2")))
            .Append(ReverseAndSwap(nonce.ToString("x2")))
            .ToString();

        Debug.Assert(string.CompareOrdinal(header, "0200000017975b97c18ed1f7e255adf297599b55330edab87803c81701000000000000008a97295a2747b4f1a0b3948df3990344c0e19fa6b2b92b3a19c8e6badc141787358b0553535f011948750833") == 0);

        var bytes = HexToBytes(header);

        SHA256 sha = new SHA256Managed();

        bytes = sha.ComputeHash(sha.ComputeHash(bytes)).Reverse().ToArray();

        var hash = BytesToHex(bytes);

        Debug.Assert(string.CompareOrdinal(hash, "0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50") == 0);
    }

    private static string ReverseAndSwap(string input)
    {
        StringBuilder sb = new StringBuilder();

        for (var i = input.Length - 1; i >= 0; i--)
        {
            sb.Append(input[i - (i % 2 == 0 ? -1 : 1)]);
        }

        return sb.ToString();
    }

    public static byte[] HexToBytes(string hex)
    {
        byte[] hexAsBytes = new byte[hex.Length / 2];

        for (int index = 0; index < hexAsBytes.Length; index++)
        {
            string byteValue = hex.Substring(index * 2, 2);
            hexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
        }

        return hexAsBytes;
    }

    public static string BytesToHex(byte[] bytes)
    {
        var output = new StringBuilder(bytes.Length * 2);

        for (int i = 0; i < bytes.Length; ++i)
        {
            output.AppendFormat("{0:x2}", bytes[i]);
        }

        return output.ToString();
    }
}