7

All the recent problems caused by transaction malleability have brought to the center stage the fact that tracking a transaction id is not good enough.

So here is my question, what is good enough?

The best I can come up with, is to create my own hash of the transaction I want to track before sending it to the network. Let's call that hash "tracking id". That hash would cover only signed portions of the transaction. The elements hashed would be

  • for all inputs: txid, vout
  • for all outputs: amount, address

Given the fact that the transaction must still be declared valid by the official client, would this "tracking id" be robust enough to track a transaction no matter how it may have been covertly "adjusted" through transaction malleability?

If this scheme does not work, do you know of any way that would allow me to safely track the transaction?

4

Since none of the answers that were given were fully fleshed enough to properly answer my question, I'm posting my own answer which synthesizes everything that has been said:

The best way to track a transaction in a way that will be resistant to transaction malleability, is to actually track only the data that has been signed. To do so, I suggest using a double SHA256 of the signed data. The documentation of the OP_CHECKSIG script operation (and it's very useful diagram form hints at which procedure should be followed.

A transaction malleability invariant "Tracking Hash" can be obtained from a pay-to-pubkey-hash transaction by:

  1. Verify the technical validity of the transaction, as is done the reference bitcoin client. This includes verifying the signatures of the transaction. This is a crucial step, if you don't do that, the tracking hash is useless.
  2. double SHA-256 hashing all of the following things:
    1. the version number
    2. the number of inputs
    3. for each input :
      1. the transaction ID of the output to spend
      2. the index of the output to spend
      3. the sequence number
      4. (Note: We intentionally do not hash the input script or the length of the input script)
    4. the number of outputs
    5. for each output:
      1. the amount
      2. the length of the output script
      3. the whole output script
    6. the lockTime

Doing this should give you a nice tracking hash, that will be the same for all equivalent transactions, no matter how it may have been modified by taking advantage of transaction malleability.

Note that this tracking hash is not part of the bitcoin protocol, so you will not find it in the blockchain, and you won't be able to look it up using blockchain.info.

  • What's the minimal amount of things to hash for this to work? – Pacerier May 22 '14 at 16:05
  • You must include every single byte that is signed, and must exclude every singly byte that is not signed. If you don't respect that, you'll be vulnerable to some type of transaction malleability. You must follow this list precisely. – LordOfThePigs May 26 '14 at 11:06
3

The signing hash is immutable, since that's precisely what you signed. Using the signing hash to track the transaction should ensure you are not vulnerable to any malleability attacks.

  • But isn't there many different signatures in a transaction (one per input)? Or is signing hash something else? – LordOfThePigs Feb 12 '14 at 23:18
  • The signing hash is the thing you sign to produce the signatures. The entire purpose of the signature algorithm is to ensure the signing hash cannot be changed, so if someone could change that without invalidating the signature, ECDSA itself would be broken and we'd have much bigger problems than malleability. – David Schwartz Feb 12 '14 at 23:24
  • So there are as many signing hashes as there are inputs, correct? – LordOfThePigs Feb 12 '14 at 23:26
  • No. There is one and only one signing hash for the transaction. – David Schwartz Feb 12 '14 at 23:27
  • I'm sorry if I appear dense, but I can't find any reference to a TX wide signing hash here. Do you have a reference where I could find out more about it? – LordOfThePigs Feb 12 '14 at 23:33
1

It's obvious that given the malleability issue you shouldn't use the transaction hash to track a transaction. If your wallet software needs to track a specific transaction it should check its inputs against the block chain, and track it based on that.

The idea is to always rely on the block chain and check inputs/outputs for yourself. Don't rely on the transaction hash for identification purposes.


Edit: One way to implement a solution is to track the referenced output instead of the transaction hash. If you get two unconfirmed transactions, that have different hashes but use the same referenced output, you know something fishy is going on. Therefore a good way to start tracking things would be to make sure the referenced outputs (within an input of a transaction) are not being used more than once.

  • Yeah, thanks. My question already makes it obvious that I know that I can't use the transaction hash. Would my tracking id solution work though? What parts of the inputs and outputs should I track against? – LordOfThePigs Feb 12 '14 at 12:42
  • Inputs are the crucial since they need to reference something in the block chain. Therefore I'd suggest tracking inputs. An output on the other hand can change (you can send different amounts to various people). – Luca Matteis Feb 12 '14 at 12:56
0

Once a transaction has 1 confirmation the Tx hash becomes immutable.

Tx hashes are widely used to track transactions (e.g., blockchain.info)

Therefore, I would rephrase your question to be:

How do I track a transaction from creation to 1 confirmation and capture the Tx hash that has been confirmed?

I think that's the right question.

Further, I'd specify that the solution should be implementable by the bitcoind API.

So... If I create Tx1 what API call should I use to determine if Tx1 has 1 confirmation?

  • 2
    You're assuming the block that holds the transaction is not orphaned. That can happen. – David Schwartz Feb 12 '14 at 21:52
  • Correct, I'm aware of that problem. And with transaction malleability, it could be that when that orphaned block gets ejected from the main chain, then the equivalent transaction that is present in the main chain (if it is) may not have the same txid either. – LordOfThePigs Feb 12 '14 at 23:20
  • You are correct - I forgot about orphaned blocks. So, you'd have to say it becomes statistically immutable after n confirmations; where n is a number that is sufficient for your purposes. Alternatively, you could say it is the transaction hash that matches your inputs and outputs contained in the longest chain. – user789235 Feb 13 '14 at 1:46
  • 1
    This may be a good rephrase of the question, but it's not an answer. Should have been a comment to the OP. – Jannes Feb 14 '14 at 9:56

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.