3

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?

3
  • Start by hashing twice. Bitcoin block hashes are double-SHA256 of the header. Feb 10, 2021 at 21:07
  • 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. Feb 10, 2021 at 21:58
  • You already have them. You should just feed hash back to SHA256; not ss.str(). Feb 10, 2021 at 22:06

1 Answer 1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.