- Dec 16, 2015
- 2,806
- 6,088
I'm starting to look at implementing a changeover of transaction signatures across a block-height hard fork.
The reason for doing so is that I want a fork chain to be independent (free) in terms of transactions - it should not be the case that issuing a transaction using the forked client creates a transaction that is seen as valid on other chains.
My first impression is that it is a non-trivial topic, and I feel I should solicit some input from the community here.
So here's what my plan is as of now. Please critique.
NOTE: I sort of mix block height (as in the fork height) and time (nLockTime). This abstracts that a timestamp will be assigned to the block that triggers the fork in the usual way.
When the fork triggers, new transactions are signed using a new transaction version (nVersion).
(to better understand the situation going forward: the block version produced by fork clients also changes at that point)
Going forward, transactions received via p2p will be rejected if their nLockTime >= the fork height and they do not carry the new tx version. If their nLockTime < the fork height and they have the old tx version, they will still be accepted (as long as the tx validates as usual).
[ NOTE: Based on a suggestion by J.Stolfi, I would amend the above to not allow old transactions indefinitely, even if their nLockTime < fork height. I would consider them valid only within a limited window after the fork, and I support Jorge's suggestions about warning the user about the upcoming fork changes to the transaction format.]
Fork clients shall mine blocks containing any transactions that are in the mempool.
This includes tx's prior to the fork (old tx version) and those after the fork which already have the new tx version. Gradually, a miners mempool will be emptied of old-versioned transactions. Miners/nodes will only be able to exchange old transactions that predate the fork within a limited time window after the fork has occurred [see the note above]. After that window has passed, old transactions would be discarded from the mempool.
Validation of transaction received in blocks must take into account that old tx versions are allowed for "old" transactions mined within a limited time window after the fork [see note above]. Transactions sporting new tx versions shall be rejected if their nLockTime predates the fork height.
It appears to me that this breaks nTimeLocked transactions which were meant to mature after the fork height, but I don't have a technical solution for that. The way I would deal with it is to allow sufficient time between release of the fork and trigger of the fork so that folks who have produced such transactions can have sufficient time to re-issue their transactions with the new tx version, so that they will be accepted as valid transactions after the fork.
This could be done at any time - even after the fork actually - as long as the signer hasn't thrown away the private keys they used to sign the original transaction. As for those who've thrown away their keys, I currently have no solution and could only say "I don't understand why you did that."
Please let me know if you see any obvious holes in this plan.
The reason for doing so is that I want a fork chain to be independent (free) in terms of transactions - it should not be the case that issuing a transaction using the forked client creates a transaction that is seen as valid on other chains.
My first impression is that it is a non-trivial topic, and I feel I should solicit some input from the community here.
So here's what my plan is as of now. Please critique.
NOTE: I sort of mix block height (as in the fork height) and time (nLockTime). This abstracts that a timestamp will be assigned to the block that triggers the fork in the usual way.
When the fork triggers, new transactions are signed using a new transaction version (nVersion).
(to better understand the situation going forward: the block version produced by fork clients also changes at that point)
Going forward, transactions received via p2p will be rejected if their nLockTime >= the fork height and they do not carry the new tx version. If their nLockTime < the fork height and they have the old tx version, they will still be accepted (as long as the tx validates as usual).
[ NOTE: Based on a suggestion by J.Stolfi, I would amend the above to not allow old transactions indefinitely, even if their nLockTime < fork height. I would consider them valid only within a limited window after the fork, and I support Jorge's suggestions about warning the user about the upcoming fork changes to the transaction format.]
Fork clients shall mine blocks containing any transactions that are in the mempool.
This includes tx's prior to the fork (old tx version) and those after the fork which already have the new tx version. Gradually, a miners mempool will be emptied of old-versioned transactions. Miners/nodes will only be able to exchange old transactions that predate the fork within a limited time window after the fork has occurred [see the note above]. After that window has passed, old transactions would be discarded from the mempool.
Validation of transaction received in blocks must take into account that old tx versions are allowed for "old" transactions mined within a limited time window after the fork [see note above]. Transactions sporting new tx versions shall be rejected if their nLockTime predates the fork height.
It appears to me that this breaks nTimeLocked transactions which were meant to mature after the fork height, but I don't have a technical solution for that. The way I would deal with it is to allow sufficient time between release of the fork and trigger of the fork so that folks who have produced such transactions can have sufficient time to re-issue their transactions with the new tx version, so that they will be accepted as valid transactions after the fork.
This could be done at any time - even after the fork actually - as long as the signer hasn't thrown away the private keys they used to sign the original transaction. As for those who've thrown away their keys, I currently have no solution and could only say "I don't understand why you did that."
Please let me know if you see any obvious holes in this plan.
Last edited: