3

I wanted to write an application that given a timestamp(text basically) and a public key will generate a merkle hash for the creation of a new genesis block. So I decided to first try and re-create the one from Bitcoin.

Unfortunately, I am failing somewhere. This is my code http://pastebin.com/sVmZgMt8

So, I should be getting this result, which is available on the Genesis Block wiki article.

04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73

However while the text in hexadecimal form is there, there is another problem I am getting. This is the output.

1d00ffff000104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73

The first thing wrong is that the nBits are displayed in an endianness different than the one above, and skimming through the Bitcoin source code a lot I failed to see how and where it was swapped, as the only line is this one

txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));

Also, there is an additional 0x04 byte in the Coinbase of the Genesis Block that I am also failing to get, and nowhere did I see it being added OR what it represents.

  • Did you try to compare your implementation to the original Bitcoin source code (line 1613)? – nivs Apr 15 '13 at 4:53
  • Yes I did, but unfortunately, it was hard to track the source code once it went into object serialization and the many overloaded constructors/member functions. But so far this is the best result I got, aside from the problems described above. – farmdve Apr 15 '13 at 5:03
4

The nBits don't exactly get swapped. The notation on the wiki is in big-endian notation, which is basically the notation you'd use when displaying it, similar how the number twelve is written 12 and not 21 (different number order) but can be stored as 21 by a computer.

Your modern computer uses little-endian, which means that if you write something like :

int myInt = 0x1d00ffff;

It will actually store that in the RAM as 0xff 0xff 0x00 0x1d

Because of that, when you take the pointer of that int, and convert it to a unsigned char*, you get the little-endian order of it. Which happens to be what the reference client does :

(const unsigned char*)pszTimestamp 

So, to put myInt in a char[], all you have to do is copy it there:

char tx[4];
int myInt = 0x1d00ffff;
memcpy(tx, &myInt, 4);
// tx now contains 0xff 0xff 0x00 0x1d

The only things that bitcoin actually swaps are network port numbers, which are stored in the memory as big endian numbers. Anything else doesn't really get swapped by bitcoin, it just stores them in the CPU's native endianness.

  • Ok, got it to work. However what is the extra 0x04 byte in front? – farmdve Apr 15 '13 at 16:01
  • Oh got that as well, all Coinbases are prefixed with a byte indicating the length of nBits, in the genesis block's case it's 0x04 :) – farmdve Apr 15 '13 at 16:11
  • Judging by the article on the genesis block, it's part of the scripting. Judging by the article on scripting, it tells the interpreter to push the next 4 bytes onto the stack – Tom van der Woerdt Apr 15 '13 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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