MIMD-0022: Private Payments #969
Dodecahedr0x
started this conversation in
MIMD
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
MIMD-0022 - Private Payments
Abstract
Enable sending tokens through a Private Ephemeral Rollup (PER) in a single transaction, following the Solana Pay standard.
Motivation
The following use-cases serve as motivations:
Alternatives considered
Below are high-level descriptions of the alternatives considered, followed by a simplified comparison. These all assume the existence of a shuttle account for the eSPL token program.
Uninitialized recipient shuttle
The goal of this approach is that the sender can initialize an empty shuttle account, not immediatly attributed to the recipient. Thanks to this non attribution, observers can't guess who the sender will make the transfer to initially. It can be illustrated like below:
sequenceDiagram participant S as Sender participant M as Solana Mainnet participant ER as EphemeralRollup participant P as Delay Program participant R as Recipient S->>M: Deposit tokens in eSPL activate S S->>M: Delegate eATA with action deactivate S M-->>ER: Receive program notification activate ER ER->>ER: Clone accounts ER->>ER: Decrypt payload ER->>ER: Execute payload ER->>P: Deposit tokens deactivate ER activate P P->>P: Initialize recipient shuttle P->>ER: Schedule crank deactivate P alt Periodically ER-->>P: Crank triggers activate P P->>ER: Undelegate recipient shuttle with action deactivate P activate ER ER->>M: Undelegate shuttle ER->>M: Execute action deactivate ER activate M M->>R: Create ATA idempotent M->>R: Transfer all tokens M->>ER: Redelegate shuttle deactivate M endStrengths
Weaknesses
Global vaults
The goal here is to have all users queue their transfers in global vault. When ready, a shuttle will take some of those transfers and partially execute them.
Users funds are initially in a user-associated PDA that periodically checks if there is room in the queue. If there is, the automation stops and their transfer intent is stored in the queue and their tokens are deposited to the global vault, otherwise the crnak continues.
A crank initially running on the shuttle periodically selects a random set of queued transfers and debits them of one chunk, then undelegates with actions to transfer the chunks to their respective recipients, and finally redelegates with an action to reschedule this crank. This prevents cases where some transaction interacts with an undelegated account: the crank on the shuttle only runs when it is delegated and is started on delegation.
sequenceDiagram participant A as Admin participant S as Sender participant M as Solana Mainnet participant ER as EphemeralRollup participant P as Chunk Program participant R as Recipient alt Initialization A->>M: Initialize token vault M->>P: Create Vault PDA activate P P->>P: Create eATA P->>P: Create shuttle P->>P: Delegate PDA P->>P: Delegate eATA P->>P: Delegate shuttle deactivate P end S->>M: Deposit tokens in eATA activate S S->>M: Create user-token PDA S->>M: Delegate user-token PDA S->>M: Delegate eATA with action deactivate S M-->>ER: Receive program notification activate ER ER->>ER: Clone accounts ER->>ER: Decrypt payload ER->>ER: Execute payload ER->>P: Deposit tokens in user-token PDA deactivate ER activate P P->>ER: Schedule queueing crank deactivate P alt Periodically, queue is full ER-->>P: Queueing crank triggers activate P P->>P: No-op because queue is full deactivate P end alt Periodically, queue not full ER-->>P: Queueing crank triggers activate P P->>P: Transfer funds from user-token PDA to global vault P->>P: Update queue P->>ER: Stop queueing crank deactivate P end alt Periodically, no pending transfers ER-->>P: Shuttle crank triggers activate P P->>P: No-op deactivate P end alt Periodically, transfers available ER-->>P: Shuttle crank triggers activate P P->>P: Partially remove transfers from queue P->>P: Transfer tokens to shuttle P->>ER: Stop shuttle crank P->>ER: Schedule undelegation with actions deactivate P activate ER ER->>M: Undelegate shuttle ER->>M: Execute action deactivate ER activate M M->>R: Create ATA idempotent M->>R: Transfer all tokens M->>ER: Redelegate shuttle with actions deactivate M activate ER ER->>ER: Reschedule shuttle crank deactivate ER endStrengths
Weaknesses
Handling errors
Errors can happen in several cases:
To address the issue of not knowing the payment status, we suggest introducing a Status PDA. It would be an ephemeral account (if the ER stops, losing this account is not a problem because the Obfuscation operations can be continued on mainnet. The PDA's address can be derived from a memo known to both parties but stored in the private payload so that outside observers can't find it. Using a crank, the status account can be updated periodically to let parties know the current status of the payment. If the status PDA is not found, it means the post-delegation action failed, and the payment can be considered as failed.
The status PDA lets parties know the transaction's status, but does not address errors that occur during chunk transfers. Using action callbacks, we can also update the Obfuscation queue and related status PDA. Since the action is a single transaction, the callback can know for sure that if an error happened, no transfers were sent and the vault is still undelegated. Using standalone actions, we can also redelegate the vault, which would restart its associated crank.
Note
If the permission program is updated to allow creating permissions as ephemeral accounts, it can be used to add privacy for status PDAs. It is not a necessary change because the address is generated from private data, so only the transacting parties are able to find it, but this would provide an extra layer of privacy.
Beta Was this translation helpful? Give feedback.
All reactions