A few more comments after discussions with @jaosef and @Mike.
TLDR: if we want to be able to update the implementation of encryption and tagging methods via protocol upgrades (which seems desirable, in order to fix bugs or improve performance), then we should store the contracts that implement them in protocol-reserved addresses (much like ethereum precompiles), which removes the need for an actual whitelist in the registry. The process of adding a new encryption method is just adding a new precompile via an upgrade, and no changes to the registry are needed.
How to store encryption method preferences
We have not yet defined how the “encryption & tagging method preference” is expressed, either on the address preimage or in the registry. One option is using the address of the contract that implements that method. However, that means that we cannot change the implementation of the contract if we find a bug or optimization without the address changing.
A better option seems to be storing an enum (1,2,3…) that maps to new methods as they are added in the registry, which requires less bytes to store, and allows a protocol upgrade to update the mapping from index to address. However, this requires to look up that mapping, which cannot be hardcoded into app code if we want to update it.
Seems like the best option is to borrow the concept of “precompile contracts” from Ethereum: we store in the addresses 0x1, 0x2, 0x3… the contracts that implement these methods. Addresses declare their preference to these short addresses, and apps make calls to them. And when the kernel needs to dispatch a call to 0x1, it looks up the code for 0x1 based on a hardcoded table in the kernel circuit.
How to update the list of valid encryption methods
When an account registers itself in the registry, the registry needs to check that the encryption method it chooses is valid. To do it, it keeps a whitelist, which needs to be upgradeable as the protocol rolls out new vetted encryption methods.
If we keep this whitelist in public storage, then a protocol upgrade must insert a new value in the registry’s public state, or craft a tx that calls a privileged update_whitelist function in the registry that takes care of doing so. The update_whitelist function should implement an access control check such that only a protocol upgrade can trigger it.
Alternatively, we could just remove the whitelist, and assume that all valid encryption methods will be stored in addresses 0x01 to 0xFF (255 should be more than enough, right?). Accounts can declare any precompile address within that range when registering. And to prevent a malicious account from registering a value that’s still unused and bricking an app, the kernel can route any call to an unused precompile address to a noop, so “encrypting a note” using a yet-unregistered encryption method does nothing.