Skip to content

Add Batch Transfer With Vesting (Closes #834)#835

Merged
DimaOrekhovPS merged 14 commits intogonka-ai:upgrade-v0.2.11from
huxuxuya:fix/BatchMessagesVesting
Mar 14, 2026
Merged

Add Batch Transfer With Vesting (Closes #834)#835
DimaOrekhovPS merged 14 commits intogonka-ai:upgrade-v0.2.11from
huxuxuya:fix/BatchMessagesVesting

Conversation

@huxuxuya
Copy link

@huxuxuya huxuxuya commented Mar 1, 2026

PR: Add Batch Transfer With Vesting (Closes #834)

This PR adds support for batch vesting transfers so governance can distribute vested
tokens to many recipients in a single proposal message.

Why

Previously, vesting transfer supported only one recipient per message.
For large distributions, proposals became too large because they required many
messages, which caused operational complexity and proposal-size limitations.

What’s included

  • Added new message and RPC:
    • MsgBatchTransferWithVesting
    • BatchVestingOutput
    • MsgBatchTransferWithVestingResponse
    • BatchTransferWithVesting endpoint
  • Implemented keeper handler for batch processing.
  • Reused/refactored shared vesting schedule logic to avoid duplication between single
    and batch flows.
  • Added validation and safety limits:
    • max recipients per batch
    • max total coin entries in batch
    • address/coin validation
    • empty/non-zero checks
  • Added events for batch operation.
  • Updated codec registration.
  • Regenerated protobuf/gRPC/API files.
  • Added tests for:
    • happy paths
    • invalid input
    • limits exceeded
    • duplicate recipient handling
    • insufficient sender balance
    • vesting epoch behavior

Result

Governance can now submit one message to distribute vesting to many addresses.

Closes #834.

@gmorgachev gmorgachev added this to the v0.2.11 milestone Mar 11, 2026
@gmorgachev gmorgachev changed the base branch from main to upgrade-v0.2.11 March 12, 2026 08:16
// Extend the schedule if necessary
requiredLength := int64(vestingEpochs)
for int64(len(schedule.EpochAmounts)) < requiredLength {
requiredLength := int(vestingEpochs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we casting to int(? It should always be a specific int (int32 or int64 usually), not a platform independent value

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new batch transfer-with-vesting transaction to the streamvesting module, enabling a single sender to create vesting schedules for multiple recipients in one message while reusing the existing vesting-schedule application logic.

Changes:

  • Introduces MsgBatchTransferWithVesting (+ BatchVestingOutput) in protobuf/API codegen and registers it for SDK interface decoding.
  • Implements keeper handling for batch transfers, including aggregation of duplicate recipients and new event emission.
  • Refactors single-transfer logic to reuse shared vesting-epoch normalization and schedule application; adds keeper tests for the new batch message.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
inference-chain/x/streamvesting/types/tx.pb.go Regenerated gogo protobuf types/service for new batch vesting message.
inference-chain/x/streamvesting/types/events.go Adds event type + attribute key for batch transfers.
inference-chain/x/streamvesting/types/codec.go Registers MsgBatchTransferWithVesting as an sdk.Msg implementation.
inference-chain/x/streamvesting/keeper/msg_transfer_with_vesting.go Refactors vesting epoch normalization + schedule application into helpers; reuses in transfer flow.
inference-chain/x/streamvesting/keeper/msg_batch_transfer_with_vesting.go New keeper message handler for batch transfer with vesting.
inference-chain/x/streamvesting/keeper/msg_batch_transfer_with_vesting_test.go Adds unit tests covering batch transfer validation and schedule creation.
inference-chain/proto/inference/streamvesting/tx.proto Adds new RPC + messages for batch transfer with vesting.
inference-chain/api/inference/streamvesting/tx.pulsar.go Regenerated pulsar API bindings for new messages.
inference-chain/api/inference/streamvesting/tx_grpc.pb.go Regenerated gRPC client/server stubs including new RPC method.

return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "too many total coin entries in batch: %d, max allowed: %d", totalCoinEntries, MaxBatchCoinEntries)
}

aggregated[output.Recipient] = aggregated[output.Recipient].Add(output.Amount...)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When aggregating duplicate recipients, the per-output len(output.Amount) <= MaxCoinsInAmount check can be bypassed: if the same recipient appears multiple times with disjoint denoms, aggregated[recipient] can end up containing > MaxCoinsInAmount denoms. That defeats the intended DoS/memory bound and can significantly increase work in applyVestingSchedule (epochs × denoms) and state size per recipient.

Consider re-validating the aggregated coin set per recipient (e.g., after the Add or after aggregation is complete) and returning an error if len(aggregated[recipient]) > MaxCoinsInAmount (and/or add a dedicated max for aggregated per-recipient denoms). Adding a unit test for this bypass case would prevent regressions.

Suggested change
aggregated[output.Recipient] = aggregated[output.Recipient].Add(output.Amount...)
aggregated[output.Recipient] = aggregated[output.Recipient].Add(output.Amount...)
if len(aggregated[output.Recipient]) > MaxCoinsInAmount {
return nil, errorsmod.Wrapf(
sdkerrors.ErrInvalidRequest,
"too many coin denominations for recipient %s after aggregation: %d, max allowed: %d",
output.Recipient,
len(aggregated[output.Recipient]),
MaxCoinsInAmount,
)
}

Copilot uses AI. Check for mistakes.
@patimen
Copy link
Collaborator

patimen commented Mar 13, 2026

/run-integration

@DimaOrekhovPS
Copy link
Collaborator

/run-integration

@DimaOrekhovPS
Copy link
Collaborator

/run-integration

@DimaOrekhovPS DimaOrekhovPS merged commit 56676be into gonka-ai:upgrade-v0.2.11 Mar 14, 2026
5 checks passed
@patimen patimen mentioned this pull request Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

We could not send vesting to many users in one proposal

5 participants