1
I wanted to help out the community and create a pure C application independent of the reference client, that given a timestamp and a public key, will produce a merkle root for creation of a genesis block.
My knowledge of C++ is very little to none. After looking at the source code, this is the relevant code
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
Which produces this merkle hash
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
I am not sure whether CScript() << 486604799 << CBigNum(4) <<... is bitshifting all of this, or simply writing it out to .scriptSig. And I am going to assume that CScript() is the constructor that initializes .scriptSig.
As I delved into the source code and following what BuildMerkleTree calls I ended up in
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
CHashWriter ss(nType, nVersion);
ss << obj;
return ss.GetHash();
}
So I started following ChashWriter, and ended up in
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj, nType, nVersion);
return (*this);
}
And I got lost there. But the closest I got was double SHA256-ing this
04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73 5000000000 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG after supposedly converting to a byte array.
And I was obviously wrong about it, as the result was not correct.
Apparently, Bitcoin uses something known as Serialization to serialize the object's variables, perhaps concatenate them, but unfortunately due to my inexperience with C++ I could not understand which variables, in what order and so on. Basically, the Bitcoin source code was more complex than I had imagined.
So my question is how I may produce a merkle hash for a genesis block, without using serialization and in C?
But I do not understand in what order they are placed. Like the order of concatenation and of which data exactly. Because in the source code, serialization of objects is used, and I am unfamiliar with that concept so I know not in what order, which variables etc. – farmdve – 2013-04-14T18:32:50.010
The bottom level of the tree should be sorted by hash, ascending from left to right. The rest is (hopefully) obvious. Forget about the serialization, that's completely irrelevant. – Tom van der Woerdt – 2013-04-14T19:03:13.073
Since I do not plan to work with anything else than a genesis block, I believe that I don't need any trees for this. – farmdve – 2013-04-14T19:09:31.823
Correct. When only working with the genesis block, just take the SHA256(SHA256(tx)). – Tom van der Woerdt – 2013-04-14T19:13:32.677
Well, while I am working on constructing a structure to contain the genesis block's transaction, how would I later SHA256 all of it? Serialization in Bitcoin in C++ is done to convert a few variables regardless of their datatype to a sequence of bytes, in C I've yet to find any standard way of doing it. – farmdve – 2013-04-14T19:33:11.173
I'd say take a look at my own bitcoin relay, which happens to be written in C. The hash is taken of the entire transaction as sent over the network via the
– Tom van der Woerdt – 2013-04-14T20:19:32.150txcommand. Thetxcommand is described here. An example transaction is included there.