-
Notifications
You must be signed in to change notification settings - Fork 166
Description
📝 Note: Implementing #1 would pretty much solve this too, with some light tweaks.
Preamble
Consider this code that's designed to prevent attackers from spamming Octane's generous offer to sign and simulate a transaction:
https://github.com/solana-labs/octane/blob/master/src/api/transfer.ts#L23-L32
That code uses a module-local Set
to track which source accounts have in-flight transactions:
https://github.com/solana-labs/octane/blob/master/src/api/transfer.ts#L7
Problem
Consecutive requests from an attacker are likely to hit the same thread/instance of the serverless function, but from what I understand this is not guaranteed.
From the Vercel docs:
For example, a Serverless Function handles an incoming request, runs some computation, and responds. If another request comes to the same path, the system will automatically spawn a new isolated function, thus scaling automatically.
In contrast, processes and containers tend to expose an entire server as their entrypoint. That server would then define code for handling many types of requests.
The code you specify for handling those requests would share one common context and state. Scaling becomes harder because it is difficult to decide how many concurrent requests the process can handle.
If consecutive requests by the attacker hit different threads running our serverless API function, they will each have different Sets
of source ids, and will permit the simulation/broadcast on each thread, rendering the defence mechanism ineffective.
Possible solution
In general, with horizontally scalable systems of lambdas, you can rely on a shared state service to implement a mutex. We could consider building in support for something like Upstash – a Redis service. We could implement the source account lock as a [Redis distributed lock[(https://redis.io/topics/distlock).