Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use batch distribute_rewards for cross-chain distribution efficiency #77

Closed
Tracked by #85
ethanfrey opened this issue Jun 27, 2023 · 3 comments · Fixed by #125
Closed
Tracked by #85

Use batch distribute_rewards for cross-chain distribution efficiency #77

ethanfrey opened this issue Jun 27, 2023 · 3 comments · Fixed by #125
Assignees
Milestone

Comments

@ethanfrey
Copy link
Collaborator

The converter contract has distribute_reward, which we use now, which is called once per each validator getting rewards and then issues an ibc packet. This is N contract calls and N ibc packets every epoch.

There is also a distribute_rewards method that takes a batch of validators (all N?). This means only one contract call (saving N-1 * 60k gas). We could also use this to make one ibc packet with all distribution info.

This requires much more complex withdraw logic in the virtual-staking contract, and first we need to be able to cover that with unit tests. This in turn is blocked on some sylvia updates, and likely some cw-multi-test updates.

But when we have those dependencies ready, this would be a nice optimization to tackle.

@maurolacy
Copy link
Collaborator

maurolacy commented Sep 13, 2023

The function to optimise is this

/// This is a batch form of distribute_reward, including the payment for multiple validators.
/// This is more efficient than calling distribute_reward multiple times, but also more complex.
///
/// info.funds sent along with the message should be the sum of all rewards for all validators,
/// in the native staking denom.
#[msg(exec)]
fn distribute_rewards(
&self,
mut ctx: ExecCtx,
payments: Vec<RewardInfo>,
) -> Result<Response, Self::Error> {
// TODO: Optimize this, when we actually get such calls
let mut resp = Response::new();
for RewardInfo { validator, reward } in payments {
let mut sub_ctx = ctx.branch();
sub_ctx.info.funds[0].amount = reward;
let r = self.distribute_reward(sub_ctx, validator)?;
// put all values on the parent one
resp = resp
.add_submessages(r.messages)
.add_attributes(r.attributes)
.add_events(r.events);
}
Ok(resp)
}

Basically by creating a batch variant of the ConsumerPacket::Distribute IBC packet.

@uint
Copy link
Contributor

uint commented Sep 13, 2023

@maurolacy Do we want to keep events in the current form (N events emitted for N validators having rewards distributed)? I guess this makes it easier for some hypothetical future indexer to index these txes?

@maurolacy
Copy link
Collaborator

I think so, yes. Let's keep the events in their current form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants