Difficulty

在 C++ 中驗證比特幣目標(難度)值的最有效方法是什麼

  • April 5, 2018

我有兩個價值觀

1. h = hash of the block (32 bytes long in memory representation - not hex)
2. bits (uint32_t)

為了使計算更容易,我們創建了一個函式難度,使得:

auto d = difficulty(bits)

現在創建這樣一個難度函式的最佳方法是什麼,我認為應該返回一個 256 位的值?

然後我正在考慮將 h 和 d 值都轉換為 uint64_t 類型的數組,並比較 msb(第 255 位)中的所有 4 個元素以確保條件成立。

還有更好的比較方法嗎?

Bitcoin Core 有自己的arith_uint256類用於計算 256 位無符號整數。arith_uint256可以arith_uint256::SetCompact在文件中找到將“位”(所謂的緊湊格式)轉換為的程式碼arith_uint256.cpp

所以你總是可以直接使用它的程式碼。這可能是一個好主意,因為如果您的版本與他們的​​行為有任何不同(例如舍入錯誤),您可能不同意比特幣核心關於塊的有效性。如果您的版本在廣泛使用的客戶端中,這將分叉區塊鏈。

我提出了以下版本,對於我定義的少數測試案例似乎可以正常工作。

首先,我們需要一個輔助函式來列印給定二進制數據的十六進制值:

void hexdump(unsigned char *data, int len)
{
   int c = 0;
   while (c < len)
   {
       cout << hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[c++]);
   }
   printf("\n");
}

現在讓我們定義接受 block.bits 並將其轉換為記憶體中的 256 位值的實際函式:

bool convert_bits(uint32_t bits, uint64_t* value, int val_len = 4)
{
   assert(val_len == 4);
   assert(value != NULL);

   if (val_len != 4 || value == NULL)
   {
       return false;
   }

   // if bits =  0x1b0404cb, hex target = 0x0404cb * 2**(8*(0x1b - 3)) 
   uint32_t x = 8 * ((bits >> 24) - 3); // number of zero bits on right
   uint64_t val = bits & 0x00FFFFFF;

   // Number of maximum bits required for val is 24.
   assert(x <= (256 - 24));
   if (x > (256 - 24))
   {
       return false;
   }   

   int startq = (3 - int(x / 64));
   int endq = (3 - int((x + 24) / 64));

   int shift = ((3 + endq) * 64 - x);
   if (startq != endq)
   {
       shift = 64 - shift;
   }

   value[startq] = htobe64(val << shift);
   value[endq] = htobe64(val >> shift);

   return true;
}

現在讓我們測試一下上面的函式:

int main()
{
   uint64_t num[4] = { 0, 0, 0, 0 };
   if(convert_bits(0x1b0404cb, num))
   {
       hexdump((unsigned char *)num, sizeof(uint64_t) * 4);
   }
   return 0;
}

這列印: 00000000000404cb000000000000000000000000000000000000000000000000

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