Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: ThePiachu on December 13, 2011, 08:17:02 AM



Title: How to create Tx Hash?
Post by: ThePiachu on December 13, 2011, 08:17:02 AM
What fields does one need to hash from a Tx in order to create the Hash that is used in the Merkle Tree?


Title: Re: How to create Tx Hash?
Post by: kokjo on December 13, 2011, 08:41:10 AM
https://en.bitcoin.it/wiki/Protocol_specification


Title: Re: How to create Tx Hash?
Post by: ThePiachu on December 13, 2011, 12:00:01 PM
Yes, I know how to create a Tx message, hash a block, I know of the ScriptSig RIPEMD use, and how to construct the Merkle Tree given the Tx hashes, but what I can't seem to find how does one create the hash used in the Merkle Tree. Do I process the entire Tx, or just parts of it (like in case of block hashes).


Title: Re: How to create Tx Hash?
Post by: kokjo on December 13, 2011, 12:27:24 PM
Yes, I know how to create a Tx message, hash a block, I know of the ScriptSig RIPEMD use, and how to construct the Merkle Tree given the Tx hashes, but what I can't seem to find how does one create the hash used in the Merkle Tree. Do I process the entire Tx, or just parts of it (like in case of block hashes).
it deppends on what you need it for... if its for signing, it just some of it. but if its for locating the full transaction, you hash the whole transaction with alle the scripts included.


Title: Re: How to create Tx Hash?
Post by: Gavin Andresen on December 13, 2011, 04:05:42 PM
Here's how to figure it out from the Satoshi client code:

The IMPLEMENT_SERIALIZE macro is used to both store transactions on disk and to serialize them into a byte-array that can be hashed.

For class CTransaction, that looks like:
Code:
    IMPLEMENT_SERIALIZE
    (
        READWRITE(this->nVersion);
        nVersion = this->nVersion;
        READWRITE(vin);
        READWRITE(vout);
        READWRITE(nLockTime);
    )

READWRITE is a wrapper that is overloaded to Do The Right Thing for all the types bitcoin deals with; for complex types like CTxOut, IMPLEMENT_SERIALIZE is (essentially) called recursively.

Expand out all of the types and, assuming I didn't screw up (always an iffy assumption), it looks like a CTransaction is serialized as:

Code:
nVersion
vin.size  (vectors are serialized as a compressed count immediately followed by their contents)
 vin[].prevout    (vin->prevout->hash followed immediately by vin->prevout->n, as 36 bytes)
 vin[].scriptSig   (CScripts are serialized as a vector of bytes)
 vin[].nSequence
 ... repeated for each vin
vout.size
 vout[].nValue
 vout[].scriptPubKey
 ... repeated for each vout
nLockTime

String all those bytes together, SHA256 them twice, and you should get the transaction hash for the merkle chain.



Title: Re: How to create Tx Hash?
Post by: ThePiachu on December 13, 2011, 07:09:39 PM
So I would hash the entire Tx as it would appear in a Bitcoin message. Okay, I`ll try that.


Title: Re: How to create Tx Hash?
Post by: kokjo on December 13, 2011, 07:14:59 PM
So I would hash the entire Tx as it would appear in a Bitcoin message. Okay, I`ll try that.
twice!


Title: Re: How to create Tx Hash?
Post by: etotheipi on December 13, 2011, 11:31:22 PM
So I would hash the entire Tx as it would appear in a Bitcoin message. Okay, I`ll try that.

Here's exactly how the Tx is laid out: 
https://bitcointalk.org/index.php?topic=29416.0

That should be the same as show on the protocol wiki, and is the same as it's stored in the blk0001.dat file and also as it's sent over the network.  Once you have that in binary form, apply sha256 twice to get your final answer.

If you want to hash a Tx for ECDSA signing/verification, that's a whole different story (although, the link above also shows how to do that, too).


Title: Re: How to create Tx Hash?
Post by: ThePiachu on December 14, 2011, 12:51:09 AM
Thanks for all your help, I managed to properly hash the Tx from the Genesis Block.


Title: Re: How to create Tx Hash?
Post by: kokjo on December 14, 2011, 08:51:49 AM
Thanks for all your help, I managed to properly hash the Tx from the Genesis Block.
+1