Earlier today, @darwinzer0 and I announced our recent work on a new SNIP proposal that allows contracts to secretly notify users when arbitrary events occur. We leverage the existing Tendermint event stack to create a private push-based notification service.
Fully private: Observers cannot determine the recipient of a notification, nor can they tell if a notification actually occurred (i.e., indistinguishable decoys)
Encrypted payloads: Notifications can include data that are only able to be decrypted by the intended recipient, similar to how execution outputs can only be read by tx sender
Tx-less subscription: Clients are able to start receiving notifications without ever having to execute the contract
Multiple channels: Contracts can create distinct notification channels, each with its own payload schema, which clients can subscribe to individually
The primary motivation began as a means to reduce the load placed on query nodes by removing the need for clients to continually query contracts. Additionally, push notifications can be multiplexed by non-SGX hardware, allowing API providers to more easily scale to meet network demands.
In this thread, we’d like to gather feedback from the community, answer questions, field criticisms, and discuss possible future directions. Please take a look at the full spec below and feel free to play with the demo app:
Fully private: Observers cannot determine the recipient of a notification, nor can they tell if a notification actually occurred (i.e., indistinguishable decoys)
Can you elaborate the indistinguishable decoys functionality? Essentially my question is how will the privacy of who is subscribed to what be preserved?
To summarise here: encrypted notifications have an id that is only known to the recipient, so observers watching the logs on the chain cannot know who a notification is meant for. However, we do detail a hypothetical sophisticated side chain attack to infer the next notification id depending on how the contract logic works. To mitigate that you could use decoys, similar to SNIP-25. Using decoys you can also send dummy notifications to no one, which is what the second part of that sentence is referring to.
The attack we describe is based on the Counter mode, but we have also detailed a TxHash mode in the spec that would prevent this kind of side chain attack. (see: SNIPs/SNIP-52.md at feat/snip-52 · SolarRepublic/SNIPs · GitHub). To implement TxHash mode we will need Slabs to add the transaction hash inside env in the contract. (Sounds like that is doable but will need to be part of a network upgrade). TxHash mode is more secure but somewhat less user-friendly on the client side because Counter mode lets you search back through the history of notifications for ones it might have missed, which would not be so easy with TxHash.
The choice of which mode to use in your contract depends on the use case. For SNIP-2x transaction-related notifications, TxHash mode would definitely be warranted. But for other cases, such as an NFT bid contract that wants to notify someone on a successfully completed auction or notification that your opponent has made a move in an on chain game, then Counter mode is probably fine.
This refers to the fact that if an execution does not produce any notifications then the contract will add an attribute to the event log using random data to produce a decoy notification, which an observer cannot distinguish from a real one.
Clients will receive a websocket message for each execution of the contract they are subscribed to. If their notification ID is present in the log, then the notification is meant for them. Client is the only party that evaluates that, hence the privacy. Even the query node does not know which messages contain actual notifications nor who they might affect.
Our PR for Private Push Notifications (SNIP-52) is going through review before it gets added to the SNIPs repo. We’ve had confirmation from slabs that env.transaction.hash will be added to 1.11, which will allow for implementation of the TxHash mode of the spec.
Please let us know if you have feedback. If have you any comments/suggestions, please make here or on the github PR: