Add Batch Transfer With Vesting (Closes #834)#835
Add Batch Transfer With Vesting (Closes #834)#835DimaOrekhovPS merged 14 commits intogonka-ai:upgrade-v0.2.11from
Conversation
| // Extend the schedule if necessary | ||
| requiredLength := int64(vestingEpochs) | ||
| for int64(len(schedule.EpochAmounts)) < requiredLength { | ||
| requiredLength := int(vestingEpochs) |
There was a problem hiding this comment.
Why are we casting to int(? It should always be a specific int (int32 or int64 usually), not a platform independent value
There was a problem hiding this comment.
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...) |
There was a problem hiding this comment.
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.
| 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, | |
| ) | |
| } |
|
/run-integration |
|
/run-integration |
|
/run-integration |
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
and batch flows.
Result
Governance can now submit one message to distribute vesting to many addresses.
Closes #834.