:::warning This doc is closed! Pls comment on and refer to https://hackmd.io/@lido/csm-v2-internal ::: # Priority Queues in CSM v2 ## Preface For CSM v2, finding a way for likely independent operators to be deposited before other permissionless operators is required. The notion of a priority queue was introduced—a queue where deposit data is requested first. It also became clear that multiple types of node operators can participate in CSM, and it makes sense to prioritize deposits to those differently. To achieve this, the idea is to introduce several prioritized queues with different priorities. ## Tech design `CSModule` keeps track of a predefined list of priority queues. Every queue is identified by its index, which also serves as its priority indicator. A queue with an index of 0 has the maximum priority. The module has a fixed amount of queues, limited by the `LOWEST_PRIORITY` deploy-time constant. As a result, the module can work with any queue in the range **[0; LOWEST_PRIORITY]**, where `LOWEST_PRIORITY` is reserved to be used as a default queue. ![image](https://hackmd.io/_uploads/BJhk3IQKJl.png) CSM v2 introduces a separate contract to the module composition called [`CSParametersRegistry`](https://hackmd.io/@lido/H1M-sLCdyx), so the configuration for separate priority queues is stored in the registry. Queue configuration looks like this: ```solidity struct QueueConfig { uint8 priority; uint32 maxDeposits; } ``` In this structure, `priority` indicates which queue to use, and `maxDeposits` shows the maximum number of validator keys a node operator can get deposited using the priority queue. A node operator can be assigned to a group identified by its `curveID`, so every `curveID` has its priority queue configuration. The configuration is not limited to using specific queues except for reserved ones. We can imagine the following setup: ``` curveID QueueConfig 0 (p0, 10) 1 (p1, 10) 2 (p0, 50) 3 (p3, 10) ... ``` ### Adding keys to the queue(s) The mechanic of adding new keys by a node operator looks like this: 1. Get the `QueueConfig` associated with the node operator's `curveID`. 2. Check if there are non-deposited and non-queued keys below `QueueConfig.maxDeposits` limit that can be put into the queue with priority `QueueConfig.priority`. 3. Add as many keys as possible to the priority queue with the priority `QueueConfig.priority` and the rest to the default one, i.e., with `LOWEST_PRIORITY`. ![image](https://hackmd.io/_uploads/ByvQ3UXKyx.png) Note that a node operator can get up to `maxDeposits`using its priority queue. In other words, the following scenario is actual: 1. NO uploads 10 (`maxDeposits`) keys and puts them in the priority queue. 2. NO changes their mind and removes all the keys. 3. NO's batch in the priority queue is skipped. 4. NO uploads 10 keys again and puts them in the priority queue since they have not received any deposits from the queue yet. ### Getting deposit data from the queues The mechanic is simple. `CSModule` goes over the queues in the order of their priority (`0 -> LOWEST_PRIORITY`) and processes batches from the queues sequentially: when one queue is exhausted, the next one is used to fetch batches. ![image](https://hackmd.io/_uploads/Syi42LmYJg.png) ### Queue(s) cleanup The cleanup mechanic works similarly to deposit data retrieval. Queues are ordered and processed by their priority, and the batches that cannot be deposited are removed from the queue where they were found. ## Migration from the old scheme To migrate the current queue to the new mechanic, a separate priority is dedicated to the queue and can't be used by any `curveID`. `LEGACY_QUEUE_PRIORITY` is set to `LOWEST_PRIORITY - 1`. As a result, we have the following range of free priorities: **[0; LOWEST_PRIORITY-2]**. Eventually, the legacy queue will be entirely deposited, and the reserved priority will be released for use in the next release of CSM (v3). ![image](https://hackmd.io/_uploads/HkBI28mtJe.png)