<blockquote>
<p>I have a class/function which will format them into a hex string, which i get as</p>
</blockquote>
<p>You don't format as hex-string, it's 80-bytes raw bytes, serialized as:</p>
<pre><code>- version (4-bytes little-endian)
- prev_block_hash (little-endian 32-bytes prev_block hash, since it's LE, you'll have multiple following 0's, not leading)
- merkle_root (little-endian 32-bytes merkle root)
- timestamp (4-bytes LE)
- bits (4-bytes LE)
- nonce (4-bytes LE)

</code></pre>
<p>I don't know how you serialize it, but here's a simple C code to build it from a struct like yours.</p>
<pre class="lang-c prettyprint-override"><code>unsigned char ser_header[80];
memcpy(ser_header, header.version, 4);
memcpy(ser_header + 4, header.prev_block_version, 32);
memcpy(ser_header + 38, header.merkle_root, 32);
memcpy(ser_header + 72, header.timestamp, 4);
memcpy(ser_header + 68, header.bits, 4);
memcpy(ser_header + 76, header.nonce, 4);
</code></pre>
<p>Then hash it.</p>

CC BY-SA 4.0
2023-05-07T03:08:53.933Z
2023-05-07T03:08:53.933Z
Davidson Souza
<p>So im trying to hash a header in C++ and I am having some trouble.
I have tried different libraries (cryptopp, openssl) can't seem to hash the header correctly.</p>
<p>This is the block which I am testing: <a href="https://www.blockchain.com/btc/block/669892" rel="nofollow noreferrer">https://www.blockchain.com/btc/block/669892</a></p>
<pre class="lang-cpp prettyprint-override"><code>header.version = 1073676288; // 3ff0000
header.previous_block = &quot;000000000000000000069237bbafea14ba06f7bdc5e192aa38875ca3fc0d0cd9&quot;;
header.tx_merkle_root = &quot;b0a2b9b8a0063e5b6818a8725ac567977805c77b6bba11f03a0c33a0cdd866ad&quot;;
header.timestamp = 1612900436; // 6022e854
header.bits = &quot;170d21b9&quot;;
header.nonce = 2792790281; // a6769909
</code></pre>
<p>I have a class/function which will format them into a hex string, which i get as: <code>0000ff3fd90c0dfca35c8738aa92e1c5bdf706ba14eaafbb379206000000000000000000ad66d8cda0330c3af011ba6b7bc705789767c55a72a818685b3e06a0b8b9a2b054e82260b9210d17099976a6</code></p>
<p>And the expected final hash of <code>000000000000000000064ec839564cc03166184f0a404d82cad9c655f714d886</code></p>
<p>I then use this hash function, and similar to get the final computed hash <code>SHA256(SHA256(blockheader))</code></p>
<pre class="lang-cpp prettyprint-override"><code>static std::string SHA256(std::string data, int size)
{
  // convert hex string to char
  unsigned char tmp;
  Crypto::hexStringToCharBinary(&amp;tmp, &amp;data, size);

  unsigned char hash[SHA256_DIGEST_LENGTH];
  SHA256_CTX sha256;
  SHA256_Init(&amp;sha256);
  SHA256_Update(&amp;sha256, &amp;tmp, size);
  SHA256_Final(hash, &amp;sha256);
  std::stringstream ss;
  for(int i = 0; i &lt; SHA256_DIGEST_LENGTH; i++)
  {
      ss &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill('0') &lt;&lt; (int)hash[i];
  }
  std::cout &lt;&lt; &quot;digest: &quot; &lt;&lt; ss.str() &lt;&lt; std::endl;
  return ss.str();
}
</code></pre>
<p>I know that I am supposed to give the sha256 the bits and not the string of hex, because it works on a bit basis, but I dont know how to do that. I am not the best at byte manipulation in C++, or hashing,
does anyone know how to do this nice and easy, if that's possible?</p>

CC BY-SA 4.0
2021-02-10T21:07:06.843Z
Start by hashing twice. Bitcoin block hashes are double-SHA256 of the header.
Pieter Wuille
CC BY-SA 4.0
2021-02-10T21:58:13.680Z
I have done that. I think I am having trouble with variable types.. getting the sha(sha) to read the bytes of the hex string, and not the string. I dont know how to do that.
Martin Bradley
CC BY-SA 4.0
2021-02-10T22:06:11.233Z
You already have them. You should just feed `hash` back to SHA256; not `ss.str()`.
Pieter Wuille
<hash><block-header><c++>
How do I hash header block with C++
Martin Bradley
# How do I hash header block with C++

(Asked by: username_0 on 2021-02-10)

So im trying to hash a header in C++ and I am having some trouble.
I have tried different libraries (cryptopp, openssl) can't seem to hash the header correctly.
This is the block which I am testing: https://www.blockchain.com/btc/block/669892
header.version = 1073676288; // 3ff0000
header.previous_block = "000000000000000000069237bbafea14ba06f7bdc5e192aa38875ca3fc0d0cd9";
header.tx_merkle_root = "b0a2b9b8a0063e5b6818a8725ac567977805c77b6bba11f03a0c33a0cdd866ad";
header.timestamp = 1612900436; // 6022e854
header.bits = "170d21b9";
header.nonce = 2792790281; // a6769909

I have a class/function which will format them into a hex string, which i get as: 0000ff3fd90c0dfca35c8738aa92e1c5bdf706ba14eaafbb379206000000000000000000ad66d8cda0330c3af011ba6b7bc705789767c55a72a818685b3e06a0b8b9a2b054e82260b9210d17099976a6
And the expected final hash of 000000000000000000064ec839564cc03166184f0a404d82cad9c655f714d886
I then use this hash function, and similar to get the final computed hash SHA256(SHA256(blockheader))
static std::string SHA256(std::string data, int size)
{
  // convert hex string to char
  unsigned char tmp;
  Crypto::hexStringToCharBinary(&tmp, &data, size);

  unsigned char hash[SHA256_DIGEST_LENGTH];
  SHA256_CTX sha256;
  SHA256_Init(&sha256);
  SHA256_Update(&sha256, &tmp, size);
  SHA256_Final(hash, &sha256);
  std::stringstream ss;
  for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
  {
      ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
  }
  std::cout << "digest: " << ss.str() << std::endl;
  return ss.str();
}

I know that I am supposed to give the sha256 the bits and not the string of hex, because it works on a bit basis, but I dont know how to do that. I am not the best at byte manipulation in C++, or hashing,
does anyone know how to do this nice and easy, if that's possible?

**Tags:** hash, block-header, c++

> **Comments:**
> **username_1**: Start by hashing twice. Bitcoin block hashes are double-SHA256 of the header.  
> **username_0**: I have done that. I think I am having trouble with variable types.. getting the sha(sha) to read the bytes of the hex string, and not the string. I dont know how to do that.  
> **username_1**: You already have them. You should just feed `hash` back to SHA256; not `ss.str()`.  

---

## 1 answers

### Answer by username_2 on 2023-05-07. Score: 1

I have a class/function which will format them into a hex string, which i get as

You don't format as hex-string, it's 80-bytes raw bytes, serialized as:
- version (4-bytes little-endian)
- prev_block_hash (little-endian 32-bytes prev_block hash, since it's LE, you'll have multiple following 0's, not leading)
- merkle_root (little-endian 32-bytes merkle root)
- timestamp (4-bytes LE)
- bits (4-bytes LE)
- nonce (4-bytes LE)


I don't know how you serialize it, but here's a simple C code to build it from a struct like yours.
unsigned char ser_header[80];
memcpy(ser_header, header.version, 4);
memcpy(ser_header + 4, header.prev_block_version, 32);
memcpy(ser_header + 38, header.merkle_root, 32);
memcpy(ser_header + 72, header.timestamp, 4);
memcpy(ser_header + 68, header.bits, 4);
memcpy(ser_header + 76, header.nonce, 4);

Then hash it.


---

