| It appears that Bitstamp did indeed use the creation transaction API in bitcoind which returns a transaction ID and they made the incorrect decision that the transaction ID returned had properties many programmers associate with IDs, like "meaning anything at all." What they should have done was waited an hour then done an O(n) scan of all transactions globally in history to find the transaction by inspecting for parameters which exactly matched the ones they provided. That is, the Bitcoin developers now say, the correct use of the create transaction API. Let me use an example programmers may be familiar with. Twilio lets you do SMS messages with three parameters: from_number, to_number, message. You are given back an SMS ID, which you can query to see the results of the SMS message (like, say, was it delivered successfully or did it fail with an error like "that telephone number did not exist"). Here's a discussion with Twilio in the bizarro world where it's like Bitcoin. Me: "Hey Twilio I created an SMS message but when I try to query it for the results it 404s." Them: "Are you sure you created the message?" Me: "Yep pretty sure." Them: "Are you sure you are looking for the right message ID in /messages/:id?" Me: "Yep, I'm using the one that I got back when I created it." Them: "Maybe it changed." Me: "... What?" Them: "Message IDs can change." Me: "They don't usually change." Them: "Of course, they don't usually change. Why have an ID if they usually changed? They only change some of the time." Me: "What determines if a message ID changes?" Them: "Oh, anyone globally can change your message IDs." Me: "That sounds a bit insecure for a system which is, by its nature, deployed in a hostile environment." Them: "Don't worry, they can't change after about an hour. Well, probably. It would be pretty expensive for an attacker to change them after an hour. Don't worry though, you'll never need an ID." Me: "I find IDs useful for querying things. Like, say, messages. Which I have to do. To see whether the message was successful or not." Them: "Well you're already downloading every message ever. Just scan through for one which matches the same from number, to number, and message contents." Me: "... You're serious." Them: "Don't worry though: they can't touch the from number, to number, or the message contents." Me: "... Does this sound a little problematic to anyone else?" Them: "It's on our wiki, noob!" [Edit: Maybe somebody thinks I'm joking. Let me point you to one of the dangerous functions. https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls... Name: sendtoaddress Parameters: <bitcoinaddress> <amount> [comment] [comment-to] Comments: <amount> is a real and is rounded to 8 decimal places. Returns the transaction ID <txid> if successful. You should naturally, upon reading this documentation, figure "I should immediately discard that transaction ID, because it could be changed instantaneously after this message call. If I instead rely on that transaction ID, I will allow malicious users to break the software I am building."] |
> Don't worry, they can't change after about an hour. Well, probably. It would be pretty expensive for an attacker to change them after an hour.
You use the term "pretty expensive" here without qualifying it. Changing a transaction encoded in the blockchain would require outpacing the current hashrate of the bitcoin network. That would require a significant hardware investment, on the order of tens of millions of dollars.
> Well you're already downloading every message ever. Just scan through for one which matches the same from number, to number, and message contents.
You make it sound as if you wouldn't have to do this if you had the transaction hash. You still need to iterate through the transactions regardless. It's just a question of whether you use the transaction hash, or derive your own from the parts of the transaction that are immutable.
Let's make your example a touch more realistic:
Me: "Hey Twilio I created an SMS message but when I try to query it for the results it 404s."
Them: "Has the message been delivered?"
Me: "I don't think so. I'm querying it shortly after I create it."
Them: "How are you querying it?"
Me: "With the message hash."
Them: "Ah, that explains it, then. A pending message may be changed before its delivered, altering the hash. This makes the hash unsuitable for identifying pending messages."
Me: "So how do I identify messages?"
Them: "Ideally you wait until they're delivered, but if you really need to check for pending messages, you can search through them looking for a message that matches on to, from and content."
Me: "That kinda sucks."
Them: "We know, but it's a difficult issue to fix. It's documented in our wiki."
Me: "What if I don't read your wiki, or follow your mailing list?"
Them: "Then should you really be running an exchange handling millions of dollars of transactions?"
Me: "... Good point."