MIMD-0023: Anti-Money Laundering #1132
Closed
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-0023: Anti-Money Laundering (AML)
Abstract
This MIMD presents a way to prevent users suspected of money laundering from using the validator. It does so by:
The limitations of this approach are:
Motivation
With the introduction of Private Ephemeral Rollups (PERs), money launderers could potentially use TEEs for their operations.
This puts MagicBlock (and in the future PER operators) at risk. Preventing money launderers from using PERs is a critical security requirement.
Alternatives considered
1. API Checks
We provide a simple API that let's users create private transfers. Running the checks before returning a transaction would prevent money laudering going through the API but would not prevent launderers from using the validator directly.
2. Checks inside the TEE middleware
Since AML checks only make sense for PER, a reasonable solution would be to run those checks inside the TEE middleware.
However, the middleware only filters user interactions, but the private payment flow is orchestrated entirely from mainnet: a user signs a mainnet transaction and the PER transfers are performed automatically by the validator, without the user sending any transactions to the TEE.
3. New middleware between the TEE validator and the mainnet RPC
By preventing updates of accounts owned by suspected money launderers, we can prevent them from using the validator.
However, this solution would have a lot less context about what is being executed and would either have to fetch data from the validator (more latency) or aggressively run AML checks (expensive).
Overview
AML results are used in several components of the validator (namely chainlink and processor). To avoid duplicating checks, a new AML component is introduced. It uses a local storage for AML checks to reduce the number of calls to the AML API. It offers a single check API
async fn check(address: Pubkey) -> AmlResult:Cloning prevention
This step consists of detecting eSPL deposits that are above a certain threshold:
Execution prevention
This step involves preventing the execution of transactions originating from a launderer. Ensuring the AML checks have been run for every signer of every transaction would be too expensive, so if we propose the following heuristic:
Handling failed checks
Once a user has been prevented from interacting with the PER, although we protected ourselves from money launderers, we still need to decide what to do next. Below are some of the possibilities.
Automatic undelegation
Once cloning has been prevented, the account is still delegated on Solana but unusable in rollups. A simple and effective approach would be to undelegate the account to avoid punishing false positives.
The downside of this approach is that since the error is internal to the validator, there is no explicit error on Solana or the PER that the user can look for. A workaround for that situation would be to add a memo transaction to the undelegation, indicating which account failed the AML test. This way, the user would eventually see an explanation in the explorer.
This undelegation can happen in two ways: either immediately after parsing the action and running AML checks, or later, via a background service. The first approach has the merit of being the fastest and could potentially use the same flow as other failing-delegation actions if we choose to always undelegate accounts with failing actions. The second keeps the chainlink component of the validator lean, but would require a ticker to check newly blocked accounts and trigger the undelegation.
Data collection
AML checks rely on the Range API, and we can hardly be more efficient internally at determining whether to block an account. However, there might be some edge cases where we should allow the account to be cloned despite failing the checks. To help inform that decision, we should collect as much information as possible when blocking accounts:
Manually validating checks
Once an address is blocked, it stays in a cache for some time, preventing any subsequent action from that user. If we want to allow the user to proceed anyway, we need a way to manually set the value in the cache. The simplest approach would be a simple CLI or script that we can run for specific addresses. However, especially in cases where specific apps request to unlock a user, we might want a more ergonomic interface.
The background service mentioned above could also provide a frontend to format some of the registered data related to blocking an address in a user-friendly way. By using the API tokens we provide to app admins, they would have a limited view of blocked users and be able to prevalidate some users. We need to keep the final decision with us, as we are the ones taking the actual laundering risk.
All reactions