To support state expiration, there are now three different types of ContractData unique, recreateable, and temporary. Temporary entries are permanently deleted when they expire, while unique and recreateable entries are sent to the deep state store on expiration. Recreateable entries may have many different version of the same key in the state store, while unique entries are guaranteed to only have a single version that exists between the ledger and the deep state store.
We need to decide how to treat keys for these different entry types. Initially, the most secure option was for each entry type to have a seperate key space. This means that for the key 0x1, UNIQUE(0x1), TEMPORARY(0x1), and RECREATEABLE(0x1) are all valid, completely independent entries that can exist at the same time. The reason for this is to prevent a TEMPORARY or RECREATABLE entry from "shadowing" a UNIQUE entry. If there was a shared key for all entry types, a buggy contract may create the entry UNIQUE(0x1). After some time, this entry expires and is sent to the deep state store. According to the security guarantees of unique entries, it should be impossible to create a new entry with the same key and "shadow" the entry in the deep state store. However, if we do not enforce separate key spaces, a buggy contract may accidentally shadow the entry by creating TEMPORARY(0x1). Because TEMPORARY entries have no strong security guarantees, they do not check the deep state store before creating the entry, allowing the UNIQUE entry to be shadowed and violate its uniqueness property. The initial intention of having separate key spaces is to prevent such bugs and ensure that UNIQUE entries are always unique even if the contract has this class of bug.