MinaFoundation / Core-Grants

21 stars 11 forks source link

RFC-0005: Protocol Upgrade to Enable Automatic Distribution of Delegation Rewards #9

Open lampardlamps opened 6 months ago

teddyjfpender commented 6 months ago

Thanks for making this PR @lampardlamps! 🙏

es92 commented 6 months ago

Just wanted to surface here, I think there was a previous plan, to (1) add binding coinbase receiver to zkApps, and then (2) have a zkApp that can manage payouts (probably yeah based on the work Gareth had done). Do we think that would be sufficient, or is more necessary? Building a complete version of that zkApp could probably be a good grant to come out of this (and something that could go into production after hard fork launch, though a fully constrained version would have to wait until coinbase receiver is added in)

lampardlamps commented 6 months ago

Just wanted to surface here, I think there was a previous plan, to (1) add binding coinbase receiver to zkApps, and then (2) have a zkApp that can manage payouts (probably yeah based on the work Gareth had done). Do we think that would be sufficient, or is more necessary? Building a complete version of that zkApp could probably be a good grant to come out of this (and something that could go into production after hard fork launch, though a fully constrained version would have to wait until coinbase receiver is added in)

Hi Evan, thanks for your comments. I was not involved in the details of the discussion. Was it determined that implementing a zkApp for this purpose would be the better choice than one on the protocol level? If so, the zkApp should be okay as long as it satisfies the requirements outlined here, namely: 1. the block producer do not have direct access to the block rewards; 2. the delegation charges are configurable onchain; 3. the rewards for each user is directly distributed/ available for claim according to the charge configurations.

lampardlamps commented 6 months ago

@teddyjfpender thanks for your comments Teddy, I've made some changes accordingly, I hope they are acceptable.

es92 commented 6 months ago

Just wanted to surface here, I think there was a previous plan, to (1) add binding coinbase receiver to zkApps, and then (2) have a zkApp that can manage payouts (probably yeah based on the work Gareth had done). Do we think that would be sufficient, or is more necessary? Building a complete version of that zkApp could probably be a good grant to come out of this (and something that could go into production after hard fork launch, though a fully constrained version would have to wait until coinbase receiver is added in)

Hi Evan, thanks for your comments. I was not involved in the details of the discussion. Was it determined that implementing a zkApp for this purpose would be the better choice than one on the protocol level? If so, the zkApp should be okay as long as it satisfies the requirements outlined here, namely: 1. the block producer do not have direct access to the block rewards; 2. the delegation charges are configurable onchain; 3. the rewards for each user is directly distributed/ available for claim according to the charge configurations.

Yep I think it would match those requirements - and yep the thought is if it can meet requirements it would be better this way than at the protocol level, since this way features can be added / removed as needed by BPs / staking pools, and without requiring HFs.

lampardlamps commented 6 months ago

Yep I think it would match those requirements - and yep the thought is if it can meet requirements it would be better this way than at the protocol level, since this way features can be added / removed as needed by BPs / staking pools, and without requiring HFs.

Thanks Evan, makes perfect sense!

EmrePiconbello commented 5 months ago

I think Gareth should get involved in this conversation. I was a follower of that project and the last update I got "because of reliance on oracles. It's not worth it because of risks" I might be recalling details wrong.

garethtdavies commented 5 months ago

I think Gareth should get involved in this conversation. I was a follower of that project and the last update I got "because of reliance on oracles. It's not worth it because of risks" I might be recalling details wrong.

The big blocker was the lack of coinbase receiver binding - as anyone could just switch the coinbase receiver and not use the zkApp, which makes the solution kind of moot. As I understand at this time, there won't be an option to make the contract immutable, i.e., permissions: None, which again means that it wouldn't be permissionless (I think this is just temporary as the crypto is likely to change). Finally, as this relies on an oracle, this would need to be very robust - I'd started some research on recursively validating multiple signatures from different oracles (circuit size was an issue otherwise, though things may have changed). So my comments there were more around launching something like this right after the hard fork, which isn't currently very feasible, or at least the benefits don't outweigh the risks, rather than long-term.

jrwashburn commented 5 months ago

While the theory of payout creativity was an exciting idea, the reality is that it's been pretty limited. This is not some application-layer capability - it's directly related to the security of the blockchain and should be treated as such. I don't think there is much upside to a bunch of creativity in this area. A zkapp/oracle-dependent solution is a workaround, and while better than our current work-arounds, this should be implemented by the protocol.

michal0mina commented 5 months ago

Intro

@lampardlamps Thank you for the proposal and writing up the RFC! It is clear that this addition is a necessary component of the protocol and the ecosystem.

That said, I find it quite high level. I think we should list various options with more specific details at a lower level. I propose we continue this comment thread to explore and refine potential solutions.

I know that @garethtdavies was quite active in this area (thank you!), this is his zkApp description: https://hackmd.io/@garethtdavies/BJH3xMpFs

Myself -- I am quite familiar with classic dPoS protocol solutions, which center around on-chain, in-protocol, in-daemon implementations. I list it below as the first one, but frankly, I think we should look for alternatives to leverage the power of ZK stack.

Each of the solutions listed below may require breaking changes, but the extent of them is very different and depends on specific details.

High level list of potential solutions

1. Daemon extension for on-chain protocol rewards distribution

This is quite straight forward:

UNKNOWN:

PROS:

CONS:

2. zkApp DISTRIBUTING the rewards

I believe this case captures Gareths implementaiton.

This is zkApp which:

PROS:

CONS:

3. zkApp ACCUMULATING the rewards

As an alternative lets consider an app:

PROS

CONS

4. ~HYBRID solution (???)~

~This is very vague idea. It would require daemon implementation that allows running zkApps as plugins, so we can remove dependency on the oracles. Basically, it would be one of the zkApp solutions listening to the network.~

~Concurrent usage of zkApps~

~This is an issue for all off-chain zkApps. Given that users interact with a zkApp with it's state hash, this state hash is different in case there is another user just before us. The optimistic concurrency solution fails here.~

~Consider this timeline:~

  1. ~zkApp at State S1~

  2. ~User A calls an app: delegate(AX, S1)~

  3. ~User B calls an app in the same slot: delegate(BX, S1)~

  4. ~User's B call is invalid as when his transaction arrives to the app it's state is S1(AX) = S2~

    ~Solutions~

    1. ~Consider another concurrency strategies and data structures. Ring buffer for users' calls? API calls batching and parameters to roll them up?~

      • ~Research needed~
    2. ~Custom child tokens. In that case every delegator receives child token and we can manage concurrency by separating state changes from the parent zkApp. The danger here is a possibility of manipulation of child token balances. Potential hard forking changes needed to manage permissions for child tokens from parent token.~

      • ~Prototype needed~
  5. ~More roll-up like architecture. The drawback here is that batching mentioned above would be less transparent.~

  6. ~Heavier client and UX handling of the concurrency issues (silent re-tries etc.)~

    Best guess effort level

FYI, Here is my best guess on level of effort to implement those:

  1. Protocol: Large, Daemon: Large
  2. Protocol: Small/None, Daemon: Small/None
  3. Protocol: Small/Medium, Daemon: Small/None
  4. Protocol: Medium: Daemon XLarge

Outro

The post got quite long... I will stop here. Please express your concerns about ideas above. We need more detailed requirements that will identify needed protocol changes. Also, from product point of view, it will shape final system which users interact with. CC: @jrwashburn @EmrePiconbello @es92 @teddyjfpender

EmrePiconbello commented 5 months ago

@michal0mina I am fully supportive of an on-chain protocol-level solution. I understand it's the most complicated option, and given our limited block space, it's also quite challenging. However, here's the thing: to my knowledge, since 2017, no POS blockchain relies on validators for reward distribution. Anyone can claim or distribute rewards, or it's fully automated. Additionally, all rewards go directly to their intended recipients without the need for trust. As regulations continue to develop, and POS operations become more clearly defined, Mina doesn't fit the standard POS model in many cases. Custody is also a concern, with many regions reviewing it due to FTX collapse. We're not part of the foundation's delegation program because of these issues(While we can make it work, it requires a lot of effort from both us and the Foundation, which we deem unnecessary at this point, since the issue won't persist after the fork). While this isn't a major concern, it's difficult to justify when all POS chains function similarly, while Mina operates differently. A significant portion of the problem stems from custody, with many regions requiring e-money processing licenses (commonly used by fintech firms and challenger banks). This could lead to many validators being forced to exit Mina in the long run or face a 20% reduction in rewards due to taxes, or potentially face various charges since we are directly involved in signing transactions, making us liable under the law. That's why we need a trustless system where custody, distribution, calculation, etc., don't rely on validators.

From what I outlined above I could only support the first option while I didn't get the daemon part of that solution. I assume because no node actually hold data we are configurating the daemon to hold data for last 2 epochs but if you can elaborate more that would be very helpful.

michal0mina commented 4 months ago

@EmrePiconbello Thanks for the comment and legal insights. I incorporated them in the big comment

Re: the daemon solution -- this is it, but I mentioned those low level details as it's serious sub-system and long term maintenance, both for developers and node operators (as it is heavy system).

jrwashburn commented 4 months ago

Regarding the cons of a daemon solution: The daemon already has the entire delegation structure for the current and next epoch. The only thing to add (data-wise) would be the block producer fee.

Separately, having the rewards be claimable, vs. auto-incrementing, would be very useful from a tax perspective to give delegators the ability to control timing of receipt of rewards. While this isn't anticipated in the daemon solution @michal0mina has written above, it is something to consider. This feature would add significantly more complication due to a) wanting to consider the rewards in pos lottery, and b) providing an accumulator to keep unpaid rewards. I don't have a strong opinion re: adding this to the specification, but it should be considered given its prevalence in other protocols.

michal0mina commented 4 months ago

@jrwashburn Thanks

Re the daemon -- I will investigate what we have now. Yes, we have the delegation ledger, but I thought it is only on BP level. Let me double check it.

About the logic that you describe:

jrwashburn commented 4 months ago

Let me double check it.

The only place to get the staking ledgers (at least that I am aware of) is to export them from the daemon using mina ledger export [staking-epoch-ledger | next-epoch-ledger] (unless they are archived by someone who has done that - a la https://minaexplorer.com/staking-ledgers

jrwashburn commented 4 months ago

For the daemon solution, I think we need to consider:

New transactions:

  1. Register Block Producer Pool - need to be able to specify Pool Fee

  2. Unregister Block Producer - consider whether this is necessary, and if so, should it change the delegation of all delegates back to themselves? This transaction would allow all delegates to be aware that the pool is exiting block production (vs. simply not producing blocks.)

We could also consider an Update Fee transaction; however, I think it is best to unregister and re-register with the new fee, so that delegates have a clear choice to accept the new fee amount. A further complication to consider would be supporting update fee - but it only taking effect for delegates after a certain date. This all seems like more trouble than it is worth and I suggest the simpler register/unregister approach. I'm certain the community will come up with monitoring solutions to alert delegates of the unregistrations, and expect wallets would notify on unregister as well.

Another advantage of this approach would be that it could create an official registry of pools / those BP's offering to accept delegations. (Today, you can delegate to anyone, and we have seen instances of people setting up a pool fee of 100% to make it more clear that the are not a pool. This registry could be used to prevent delegating to people that do not want delegations.)

michal0mina commented 4 months ago

@jrwashburn re the delayed update fee, it would be reasonable to apply at least the same delay as for delegations (epoch+1). If there is need for signalling, it may be increased. Also, it's worth considering adding constrains (e.g. max 2x increase, or max 50% increase)

Lack of update mechanism would be painful for managing ecosystem of your users. Some sort of inheritance of the old delegators is surly helpful.

Sventimir commented 4 months ago

I'm no expert in legal issues, but from purely technical point of view the simplest solution is to bake it into the protocol. Very simply, whenever the node constructing a block pays themselves a coinbase reward, it also scans the staking ledger in search of accounts delegating to them and immediately distributes the rewards among them. It may or may not add explicit transaction for each thus paid reward. While this is not necessary from the protocol's perspective (validators can compute those rewareds for themselves from the information already included in the block), it'll make it much easier for external software like indexers or Rosetta to figure out what's going on in the ledger (without those transactions they'd basically need to replicate the logic).

Putting this into a zkApp, while probably could be done without changing the protocol, will require someone to run the zkApp, so it's still up to a BP whether or not they run the zkApp before or after having produced a block. It does not eliminate the trust issue.

However, delaying the payment of these rewards on the protocol level complicates the system immensely. The unclaimed rewards must be kept somewhere so that total currency amount is predictable. Moreover, it forces us to implement an additional transaction type (claim rewards), which will have to be included in some future blocks. Also the information about who is entitled to claim how much must be stored somewhere. It cannot be computed from history unless we set a time limit after which unclaimed rewards are considered forefeit. On the other hand, implementing it in a zkApp seems relatively straightforward (all the information above will be stored in zkapp's state, probably even off-chain). So if we deem this feature really valuable, it's a strong argument for a zkapp solution.

jrwashburn commented 4 months ago

it would be reasonable to apply at least the same delay as for delegations (epoch+1). If there is need for signalling, it may be increased. Also, it's worth considering adding constrains (e.g. max 2x increase, or max 50% increase)

@michal0mina I agree these provisions mitigate the concern - and since monitoring by the delegator is necessary in every solution, as long as they would have a reasonable amount of time to re-delegate before the change, this overcomes my objections. I think Epoch +2 is necessary since the Epoch+1 staking ledger would already be baked.

Edited to add: In case it is not clear - I still think we want a registry with register/unregister transactions.

0xstardust commented 4 months ago

This thread seems very comprehensive. Interestingly, this decision has some downstream effects. At Kintsu we see a major overlap between this thread and the liquid staking RFC

In terms of making a scalable and secure liquid staking protocol, delegation rewards should be permissionless and trustless, and ideally, there is a simple way to claim rewards on-chain. Alternatively, there can be some runtime call made arbitrarily that allows rewards to be claimed.

michal0mina commented 4 months ago

Update:

  1. I removed issues related to concurrency. It's too close to implementation and likely solved by actions.
  2. Added important challenge/unknown with in-protocol solution: it may affect blockchain tip circuit

We also discussed deeper zkApp designed that would worked based on epoch's staking ledger. @mitschabaude would you be able to summarize the design and potential issues/blockers?

cc: @es92