4

Originally posted to StackOverflow but with no response. Thought I might have better luck here.

I've successfully created a Bitcoin transaction in C# according to the protocol specifications. Here's the transaction in binary:

010000000162EF5D87E91090453009860C6F135EA2A490133B2633F8F7BA014889F5FF7E4A000000008A4730440220497E2D3F9BBBC0C122D839968FF880514440CED08A71D28E614FF4C871964024022049687008E4AF72682992325F17E95DA382D63E3FB14605A81B4498DFF9210E310141040BCF1BECF4EF6A5C24FD790CA86E8DCDFA3538CB97E99C254F84D209CFE47BFC6BF3B11ACA05DB7C7638301711070F176E848B650A406EB7AFC30AA9EA242489FFFFFFFF02404B4C00000000001976A9140A24F0387F05A6EECD1F8B327BB442EAB767CBC888ACCA165E00000000001976A914F8FB3B4E5D75652795DD13B209E0BE7BBD66B5D488AC00000000

I know the transaction is solid because the BTCs were transmitted properly. Furthermore, pasting my transaction above into this validator indicates the correct values.

What's stumping me is how the official transaction ID is generated. Everything on the Bitcoin and StackOverflow StackExchange sites indicate that it's generated by hashing the transaction bytes twice. I tried to do so as follows:

const String txHex="010000000162EF5D87E91090453009860C6F135EA2A490133B2633F8F7BA014889F5FF7E4A000000008A4730440220497E2D3F9BBBC0C122D839968FF880514440CED08A71D28E614FF4C871964024022049687008E4AF72682992325F17E95DA382D63E3FB14605A81B4498DFF9210E310141040BCF1BECF4EF6A5C24FD790CA86E8DCDFA3538CB97E99C254F84D209CFE47BFC6BF3B11ACA05DB7C7638301711070F176E848B650A406EB7AFC30AA9EA242489FFFFFFFF02404B4C00000000001976A9140A24F0387F05A6EECD1F8B327BB442EAB767CBC888ACCA165E00000000001976A914F8FB3B4E5D75652795DD13B209E0BE7BBD66B5D488AC00000000";

SHA256Managed sha256Hasher=new SHA256Managed();
Func<byte[],byte[]> doubleHash=(bytes)=>{
    return sha256Hasher.ComputeHash((sha256Hasher.ComputeHash(bytes)));
};
String txidHex=Utils.ToHex(doubleHash(Utils.FromHex(txHex)));

Utils.ToHex() and Utils.FromHex() are helper functions copied from StackOverflow which convert between byte[] and a hex string.

The code above yields a txidHex value of 27E6C3EF18D14FB49CBAC182BBDB47FC9D6F79DA65C101873207B60A957852A7 but searching BlockExplorer.com for that particular txid yields no results.

I mentioned earlier that my transaction did execute properly. It turns out that it did so using a txid of 11172aed3a61fe64ae82cb02e886757d352a4452f956a0703d0809880538ba58. If you paste that txid into BlockExplorer you'll see my transaction.

Which leads me to my question: Given a valid transaction byte stream (byte[]), how does one correctly compute a transaction ID?

Thanks.

1 Answer 1

3
  1. You've forgotten to convert from internal byte order (used in transactions to specify outpoints,) to output byte order (displayed to users.) Reverse the bytes after the second hash.

    See also: How do I calculate the txid of this raw transaction?

  2. The transaction you've included in your question and the transaction on the blockchain are slightly different. However, since they reference the same outpoint, they cannot coexist in the blockchain.

    Blockchain:

    TXID: 11172aed3a61fe64ae82cb02e886757d352a4452f956a0703d0809880538ba58
    
    010000000162ef5d87e91090453009860c6f135ea2a490133b2633f8f7ba014889f5ff7e4a00000000
    8b48304502205abb829faec8571a6469d40edbceb7938dbb5eeb0efa5b6b284d9730eb8e90a7022100
    c0aec347ffa72ed22057a821b0219e114a3d2686eb67904403529eac4e2c7c260141040bcf1becf4ef
    6a5c24fd790ca86e8dcdfa3538cb97e99c254f84d209cfe47bfc6bf3b11aca05db7c7638301711070f
    176e848b650a406eb7afc30aa9ea242489ffffffff02404b4c00000000001976a9140a24f0387f05a6
    eecd1f8b327bb442eab767cbc888acca165e00000000001976a914f8fb3b4e5d75652795dd13b209e0
    be7bbd66b5d488ac00000000
    

    Question:

    TXID: a75278950ab607328701c165da796f9dfc47dbbb82c1ba9cb44fd118efc3e627
    
    010000000162ef5d87e91090453009860c6f135ea2a490133b2633f8f7ba014889f5ff7e4a00000000
    8a4730440220497e2d3f9bbbc0c122d839968ff880514440ced08a71d28e614ff4c871964024022049
    687008e4af72682992325f17e95da382d63e3fb14605a81b4498dff9210e310141040bcf1becf4ef6a
    5c24fd790ca86e8dcdfa3538cb97e99c254f84d209cfe47bfc6bf3b11aca05db7c7638301711070f17
    6e848b650a406eb7afc30aa9ea242489ffffffff02404b4c00000000001976a9140a24f0387f05a6ee
    cd1f8b327bb442eab767cbc888acca165e00000000001976a914f8fb3b4e5d75652795dd13b209e0be
    7bbd66b5d488ac00000000
    
4
  • Thanks, man.. This bitcoin protocol is some fascinating stuff! I'm going to dig into the info you've provided. Commented Sep 3, 2015 at 14:51
  • 1
    It's just weird mostly, the endianness of elements in transactions flips for no discernible reason. There's no standard for it in Bitcoin whatsoever. Just be aware that hashes for blocks and transactions are internally little endian but are displayed big endian to users.
    – Claris
    Commented Sep 3, 2015 at 17:13
  • Wow, ok, I think I get it now. Everything you stated makes sense but it leads me to a different question: Why is the transaction that was finalized in the block chain slightly different from what I submitted in my original question? The inputs/outputs are all correct. Everything looks good. Yet the transaction bytes are slightly different. Commented Sep 3, 2015 at 20:11
  • 1
    B/c your Tx has a different signature 48304502205abb829faec8571a6469d40edbceb7938dbb5eeb0efa5b6b284d9730eb8e90a7022100c0aec347ffa72ed22057a821b0219e114a3d2686eb67904403529eac4e2c7c260141040bcf1becf4ef6a5c24fd790ca86e8dcdfa3538cb97e99c254f84d209cfe47bfc6bf3b11aca05db7c7638301711070f176e848b650a406eb7afc30aa9ea242489 Vs 4730440220497e2d3f9bbbc0c122d839968ff880514440ced08a71d28e614ff4c871964024022049687008e4af72682992325f17e95da382d63e3fb14605a81b4498dff9210e310141040bcf1becf4ef6a5c24fd790ca86e8dcdfa3538cb97e99c254f84d209cfe47bfc6bf3b11aca05db7c7638301711070f176e848b650a406eb7afc30aa9ea242489 Commented Sep 4, 2015 at 10:52

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.