bitcoin/bitcoin — pull request #3509 by cozz (2014-01-11 00:17:21+00:00)
Title: Transaction expiration

Motivation
Transaction expiration is a fallback solution for never or too slow confirming transactions. Unconfirmed transactions expire after about 36 hours, if not included in a block by miners.
The coins are credited back to the wallet and free to use again, just like sending the transaction had never happened. The transaction stays in the wallet, marked as expired. If someone would sync his wallet from scratch, the expired transaction would not appear anymore, because obviously it is not part of the blockchain.

Implementation
Abusing vin[0].nSequence for timestamping the transactions. Do not remove any of the original features of the field, even this pull #2340 would still be possible.
People actually using the nLockTime features can decide, if they want to go with the timestamp, sending maximum of 1 tx per second, or start their sequences at, lets say, 2 billion. This would equal sending transactions "never expiring", just like it is now.

Block version 3
Blocks version 3 do not allow expired transactions. Introduced same as block version 2 by a 95% majority softfork. Expired transactions are checked against blocktime, not local time, to avoid chain splits.

Deployment
Needs staging, but no hardfork. Older versions would not remove expired transactions from their mempool and consider follow-up transactions as double spend. So Step 1 would be introducing block version 3, the relay rule and the mempool removal. Then if block v3 and, lets say, 50% of all nodes have upgraded, transaction expiration can be introduced.

Relay
The relay rule is: do not relay transactions expiring in 24 hours or less

Mining
CreateNewBlock does not include transactions which would expire in 1 hour or less. This is a safety threshold because mining software may change the timestamp afterwards, resulting in mining an invalid block, containing expired transactions.

Timeline
0 - CreateTransation
12hs later: stop relaying the transaction, other nodes would reject it, because it expires in 24 hours or less
35hs: 1 hour before expiring. CreateNewBlock does not include the tx anymore (reason see above).
36hs: transaction expires. nodes remove it from their mempool.
38hs: the wallet checks against block median time, not local time and adds another hour, to ensure the transaction is really expired and cannot appear in blocks anymore. So about ~2hs late, the wallet marks the tx as expired and frees the coins.
Resulting in a total time of about 38 hours, from creating until expiring in the wallet.

Faking
It is allowed to fake your timestamp into the future, for whatever reasons. This can increase expiration time up to "never expiring".
The relay rule is 24 hours, so you can fake your timestamp up to 12 hours into the past. This can reduce expiration time from 36 down to max 24 hours.
If you fake more than 12 hours in the past, your transaction would not get relayed by other nodes anymore. If you fake more than 36 hours in the past, you would create an already expired transactions. This doesnt make sense anyway.
This is not only about faking, but also misconfigured clocks up to 12 hours are no problem.

System clock
If transaction timestamping is on (default), the wallet refuses to create a transaction if your system clock is more than 12 hours behind the best block time. This is to ensure nobody creates an already expired transaction on accident.

Off switch
There is an option "bitcoin-qt -txtimestamp=0".
If someone does this, transactions are not timestamped anymore. This equals sending "never expiring" transactions, just like it is now.

Expiration times
"Long" expiration times are good, because:
- Merchants accepting 0-confirmations have at least 24 hours for every transaction to get confirmed, until it would expire.
Allowing short expiration times could cause them troubles.
Also such merchants should not only ask "Has the transaction been double spended", but also "Will it probably be confirmed". Transaction expiration makes this even more clear.

- Transaction expiration is a fallback solution only. Not something that should be part of peoples usual workflow.
Otherwise people would always start with a free transaction, and if it expires after an hour, try again, spamming the network.
So allowing short expiration times would be an unnecessary waste of network resources.
People sending a not confirming transaction have to wait about 38 hours, for the transaction to expire. Then they can decide, if they want to send the transaction again, maybe with a higher fee this time...

Chainfork
It is very unlikely, a transaction the wallet marked as expired suddenly appears in block. Basically only in chainfork scenarios possible.
If this happens for whatever reasons, the transaction will be unmarked expired, and gets confirmed as normal.
If then another longer chain would win again, the transaction could expire again. But even more unlikely scenario here.
But still the wallet would handle these scenarios correctly.

Screenshots
Expired transaction:
http://imageshack.com/a/img541/8103/h8j6.png

Overviewpage shows [expired]:
http://imageshack.com/a/img542/5076/be8y.png

Description of unconfirmed transaction shows expires in x hours:
http://imageshack.com/a/img856/8558/66ls.png

RPC
- listtransactions has a new filter attribut, showing expired transactions only:
listtransactions "*" 10 0 "expired"
- WalletTxToJSON shows a boolean expired true/false

Notify
-expirenotify= can notify an external script when a wallet transaction expires

Testing
I have tested this locally, modifying the other necessary code parts, to test and debug the code part being tested. Tested all added code parts.
I also tested the scenarios with expiring, then unexpiring again and what happens to the balances, unspent outputs etc. in these scenarios. Or what happens if transaction B depends on A, then A expires etc...
Not tested payment request, but there shouldnt be any difference, I guess.
No testplan or automated tests currently.