Json-Rpc

MerkleRoot 需要交易雜湊來建構 merkle 樹……這是 getblocktemplate 響應中的“雜湊”鍵/值還是“數據”?

  • February 12, 2022

我已經創建了一個解析 Json 對象和值的函式,就在我認為沒有什麼可以阻止我的時候,就在我覺得自己是區塊鏈之王並且我終於可以加入挖礦競賽的時候…..我得到一個痛苦的提醒/現實檢查……

getblocktemplate 中的每個事務都有這些作為鍵和它們的值。


每個事務數組中的內容列表中的哪個鍵值是我的 merkleroot 函式,應該用來建構 merklerot 雜湊……是它**data還是hash?還是它txid**?

Merkleroot 需要交易雜湊……那麼它是雜湊Json Key 還是數據Json Key ?


提前致謝

正如Pieter-Wuille解釋的那樣,但細節更清楚……


在比特幣探勘過程中計算 merkleroot 所需的交易數據是 getblocktemplate 響應返回的“txid”密鑰。這適用於非見證交易處理。

為了使用見證數據處理交易,您需要獲取“雜湊”鍵值!

這完全取決於您是否希望您的礦工處理帶有見證標籤的交易。



來自getblocktemplate回應


data- 原始交易數據。

txid- 原始交易數據的雙重雜湊輸出。

hash- 見證數據交易的見證雜湊輸出。



這是我自己開發的一個工作 merkleRoot 函式。按預期工作。


#include <iostream>
#include <vector>
#include "sha256.h" // Your sha256 solution with hex parsing function

using std::string;
using std::vector;
using std::cout;


string MKccx(vector<string> &transactions_vector)
{
   string hash;
   string temp1;
   int x = 0, d = 0;
   vector<string> calculate_tx;
   // calculate_tx[0] = SwapPerRound_2bits(coinbase_hash); // Store swapped endian format in vector index 0
   if (transactions_vector.empty())
   {
       std::cout << "\n" << "ERROR! NO TRANSACTION FOUND IN ARRAY!!... NOT EVEN A COINBASE TRANSACTION!!!... EXITING FUNCTION!" << "\n \n";
       throw;
   }
   else if (transactions_vector.size() == 1)
   {
       hash = transactions_vector[0];
       return hash;
   }
   for(int i = 0; i < transactions_vector.size(); i++) // Swap 2 bytes and reverse order of all txid's within transactions array
       transactions_vector[i] = SwapPerRound_2bits(transactions_vector[i]);

   while(true)
   {
       int z = 0;
       if (transactions_vector.size()%2 == 1) // IF SIZE OF VECTOR % 2 == 1
       {
           temp1 = transactions_vector[transactions_vector.size()-1]; // STORE VALUE OF LAST VECTOR INDEX TO TEMP1
           transactions_vector.push_back(temp1); // ADD THAT VALUE INTO VECTOR
           for(int i = 0, z = i+1; i < transactions_vector.size(); i+=2)
           {
               hash = transactions_vector[i] + transactions_vector[z]; // Concatenate txid pairs together
               hash = double_Hex_sha256(hash); // DoubleHash concatenated txid's
               calculate_tx.push_back(hash);
               z+=2;
           }
           for (int i = 0; i < calculate_tx.size(); i++)
           {
               temp1 = calculate_tx[i];
               transactions_vector[i] = temp1;
           }
           transactions_vector.resize(calculate_tx.size());
           if (calculate_tx.size() == 2)
           {
               hash = calculate_tx[0] + calculate_tx[1];
               hash = double_Hex_sha256(hash);
               hash = SwapPerRound_2bits(hash);
               return hash;
           }
           calculate_tx.clear();
       }
       else if (transactions_vector.size()%2 == 0) // IF SIZE OF VECTOR % 2 == 0
       {
           for(int i = 0, z = i+1; i < transactions_vector.size(); i+=2)
           {
               hash = transactions_vector[i] + transactions_vector[z]; // Concatenate txid pairs together
               hash = double_Hex_sha256(hash); // DoubleHash concatenated txid's
               calculate_tx.push_back(hash);
               z+=2;
           }
           for (int i = 0; i < calculate_tx.size(); i++)
           {
               temp1 = calculate_tx[i];
               transactions_vector[i] = temp1;
           }
           transactions_vector.resize(calculate_tx.size());
           if (calculate_tx.size() == 2)
           {
               hash = calculate_tx[0] + calculate_tx[1];
               hash = double_Hex_sha256(hash);
               hash = SwapPerRound_2bits(hash);
               return hash;
           }
           calculate_tx.clear();
       }       
   }
}// Successful compilation on 06/02/2022



int main(int argc, char const *argv[])
{
   // HARDCODED TXID'S 
   vector<string> transaction = {"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87","fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4","6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4","e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d","c02092b00aa0aea8463c624ccebdb0efdb18347068aa48c3d1b42766ca7e92ba"};

   vector<string> block100000 = {"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87","fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4","6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4","e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"};

   vector<string> transaction2 = {"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87"};

   vector<string> transaction3 = {};
   string merk;
   merk = MKccx(transaction3);
   std::cout << "MerkleRoot Hash is : " << merk << "\n \n";
   // std::cout << "Merkle hash of Block 100,000 is : " << merk << "\n \n";

   return 0;
}

SwapPerRound_2bits()- 無論您使用什麼解決方案來交換字節順序

double_Hex_sha256()- 等效於 sha256(sha256());



想知道這一切是如何結合在一起的嗎?

您需要一個 JSON 庫來將事務處理到您的 C++ 程序中

如果您還沒有可用的 JSON 解析器/序列化庫,那麼我推薦用於 JSON 解析和序列化的nlohmann json 庫

只需將其單個標題“.hpp”文件包含在項目文件夾中,您就可以開始了!

使用了一個小批處理腳本,但沒有任何高級功能。

#include "json.hpp" // for json serialization parser
#include <fstream> // for ifstream
#include <stdlib.h> // for system calls
#include "windows.h" // if on windows
using namespace nlohmann;
using std::ifstream;


inline void RunCommand_With_Output_Without_SYMBOL_Defined(string Command_To_Run, string Output_FileName)
{
   string xx_combine = Command_To_Run + " >" + Output_FileName;
   char run_command[xx_combine.length()];
   strcpy(run_command, xx_combine.c_str());
   system(run_command); // execute the command 
} // Successfully compiled on 20/01/2022 10:20PM


void GETBLOCKTEMPLATE()
{
   string getblocktemplate_syntax = "cd \"C:\\Users\\YOUR DESKTOP NAME\\Desktop\\Z Code\" && call gt.bat";
   string filename = "getblocktemplate_Response.json"; // Create file Name
   RunCommand_With_Output_Without_SYMBOL_Defined(getblocktemplate_syntax, filename); // create json file with getblockresponse output
} // Successfully compiled on 31/01/2022 11:30AM



int main(int argc, char const *argv[])
{
   // DYNAMIC APPROACH FOR USAGE 
   string merk;
   GETBLOCKTEMPLATE(); // Call getblocktemplate() 
   ifstream file_input("getblocktemplate_Response.json"); // Open file
   json object = json::parse(file_input); // Parse json data
   file_input.close(); // close file
   vector<string> Txid_Retreiver; // vector for holding transactions

   auto &Array_Txid = object["transactions"]; // Create object pointing to 'transactions' array
   for(auto &target : Array_Txid) // Traverse through transaction array
       Txid_Retreiver.push_back(target["txid"].get<std::string>());
   

   merk = MKccx(Txid_Retreiver);
   std::cout << "MerkleRoot Hash is : " << merk << "\n \n";

   return 0;
}

這就是我成功的方式。

希望這可以幫助某人。

乾杯….

交易 Merkle 樹的根儲存在塊頭中,是根據各個交易的txid值(剝離見證後其數據的雙 SHA256)計算得出的。

見證 Merkle 樹的根儲存在 coinbase 輸出中(僅包含隔離見證交易的塊需要,參見 BIP141),是根據交易的雜湊值(包括見證數據的雙 SHA256)計算的。

我建議您研究現有挖礦軟體的原始碼,而不是詢問有關該過程的每個微小細節的問題。

引用自:https://bitcoin.stackexchange.com/questions/111223