Great points, thanks for bringing it up @im_uname and @cculianu! That definitely needs to be addressed in the spec.
One useful observation: any locking bytecode with a PREFIX_TOKEN
(0xd0
) is currently provably unspendable. That’s not true for all occurrences of 0xd0
in any locking bytecode, but because 0xd0
is an unknown opcode, and an OP_IF
/OP_ENDIF
block can’t cross from unlocking to locking bytecode (also – push-only enforcement since Nov 2019), we know that 0xd0
can not be the first byte in any successful locking bytecode evaluation (and this has been the case since Satoshi).
So until the upgrade, all outputs with a 0xd0
prefix are practically equivalent to OP_RETURN
outputs, and can reasonably be pruned from the UTXO set at upgrade time. (In fact, implementations could reasonably prune lots of other provably unspendable UTXOs from their databases, but in most other cases that probably wouldn’t be worth the effort, makes UTXO commitments harder to standardize, etc.)
After that, there shouldn’t be any need to keep track of “fake token” outputs. While it still requires some activation logic, at least node implementations don’t have to pay a cost after the upgrade block.
One caveat with this strategy (and if we go with it, should be in the spec) any token transactions prepared in advance of the upgrade should use locktime to ensure the transaction isn’t included in a pre-upgrade block. (Even if the transaction is broadcasted after the new rules are expected to be in effect, it’s still possible for a backdated re-org to burn those funds.) Of course, creating tokens doesn’t require significant funds, so many users might not care if their token-creating dust gets burned by a malicious re-org (especially people creating tokens in the first few blocks, many will just be upgrade lock-in transactions). But worth mentioning for completeness.
Related, I think this is also the right strategy for handling “improperly encoded token prefixes” after activation. If PREFIX_TOKEN
is followed by an invalid token encoding, we can’t really assume the locking bytecode was intending to encode tokens (and, e.g., attempt to somehow slice off the invalid token prefix to allow the BCH dust to be spent). Instead, it’s sending dust to a provably unspendable output, and can just be treated like any OP_RETURN output. (The transaction would be non-standard anyway due to the unrecognized contract type, so in practice this would only happen if a miner deliberately mined the nonstandard transaction.)