Chialisp does not directly enable this capability. There are only conditions to make a coin that may be spent after a certain timestamp or block height. Coin spends can only become valid; they can never become invalid.
There are at least 4 reasons for this:
-
To keep CLVM separate from the mempool -- When a block is farmed, the local node executes the CLVM from all of the coin spends in that block. The mempool only contains the output of this execution. Thus, the CLVM code execution is kept separate from the mempool, and the CLVM does not need to examine the blockchain's state in order to execute. If coin spends could become invalid, then the CLVM would need to examine the blockchain's state, which would require special handling in the mempool (and possibly cause other problems).
-
To preserve mempool efficiency -- If a coin spend depended on determining the timestamp or height of the last confirmed block, as would be required if coin spends could become invalid with time, then the output of the CLVM from this spend would need to be executed with each block, in order to determine if it is still valid. If the mempool became full of such transactions, then the entire mempool would need to be re-calculated with each block. This would be extremely inefficient and a potential attack vector.
As it stands with CLVM's implementation, coin spends only need to be executed once. The mempool can safely assume that the spend has not become invalid simply because time has passed, so there is no need to re-execute the code.
- To keep reorg logic simple -- Small reorgs are rare in Chia, but still possible. If coin spends could become invalid with time, then they also could become invalid in a reorg. Any coin spends that depended on the original would then be invalidated. Sorting through the ripple effects of this behavior would require messy logic that would invalidate other spends, potentially even if they were only distantly related to the original.
Note that this problem doesn't exist when coin spends can only become valid with time. In a reorg, an invalid spend could become valid; any resulting coin spends would also remain valid. As a result, there would be nothing to unwind.
- To prevent censorship -- If someone attempts to spend a coin that is about to be made invalid, the farmer of the next transaction block could refuse to include that coin spend, thus making the coin unspendable forever. This is a slippery slope -- any coin spend that will become invalid in the future could be censored until the final valid timestamp or block has been reached. The only way to guarantee that such a coin is spendable would be for the owner to farm the block in which it is spent.
A related problem would occur if the coin spend didn't add a large enough fee to be included in the next block. This could be avoided by adding a larger fee, but the problem that a valid coin spend could become invalid still would exist.
Recommended Solution
Because of the problems listed above, any solutions to making a coin spendable until a certain timestamp or block height would need to come from outside the core CLVM implementation.
Our current recommendation: First, create Coin A
, which will run a CREATE_COIN_ANNOUNCEMENT
condition when it is spent. Next, create Coin B
, which uses the ASSERT_COIN_ANNOUNCEMENT
condition for Coin A
's announcementID. A spend of Coin A
will automatically invalidate any attempts to spend Coin B
forever.
A similar (but slightly more complex technique) would be to use a singleton instead of a standard coin. Updating the singleton automatically would invalidate a coin spend, and the singleton could be reused to invalidate future spends. This technique could also be used to invalidate offers.