Recently, there have been several issues with LIFETIME_EXTENSION implementation details. To briefly summarize, the idea behind LIFETIME_EXTENSION entries is to provide a way to bump large, primarily read-only data without having to rewrite the entire LedgerEntry. This is intended for WASM blobs, which are almost never changed and where the write costs dominate lifetime extension costs. The current design has the following issues:
-
LIFETIME_EXTENSION entries are not concurrent in their current implementation. Every entry in the RO footprint is bumpable via a LIFETIME_EXTENSION, meaning there is a possible, implicit LIFETIME_EXTENSION write for each RO key. This implicit write of a read-only structure is complicated and diffcult to implement in a parallel way.
-
BucketList invariants must be relaxed. Because LIFETIME_EXTENSION entries have a separate LedgerKey than the DATA_ENTRY they reference, but can still merge into a DATA_ENTRY, we have weird edge cases. For example, currently an INIT + INIT entry with no DEADENTRY in between is valid given the behavior of LIFETIME_EXTENSION merging. This also has negative effects for downstream system ingestion invariants.
-
Meta is difficult to consume. Downstream systems must process a new type of LedgerEntry (LIFETIME_ENTRY) that is fundamentally different than other ledger entry types.
The issue is LIFETIME_EXTENSIONS break too many assumptions of the system. Namely, that a key can be marked as RO but is still modified (at least to some extent), and that a LedgerEntry can merge with another LedgerEntry that is is related to, but that has a different key.
I think the core issue is that our solution to the given problem is too general. In practice, ContractCode is the only entry type where read-only bumps are strictly necessary. Other entry types are either frequently written, or if they are read-only, are small enough such that write fees during bumps are still low (like auth entries).