mukan-sdk/x/group/keeper/proposal_executor.go
Mukan Erkin Törük abb1ff956e
Some checks are pending
Build SimApp / build (amd64) (push) Waiting to run
Build SimApp / build (arm64) (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
Build & Push / build (push) Waiting to run
Run Gosec / Gosec (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Checks dependencies and mocks generation / Check go mod tidy (push) Waiting to run
Checks dependencies and mocks generation / Check up to date mocks (push) Waiting to run
System Tests / setup (push) Waiting to run
System Tests / test-system (push) Blocked by required conditions
System Tests / test-system-legacy (push) Blocked by required conditions
Tests / Code Coverage / split-test-files (push) Waiting to run
Tests / Code Coverage / tests (00) (push) Blocked by required conditions
Tests / Code Coverage / tests (01) (push) Blocked by required conditions
Tests / Code Coverage / tests (02) (push) Blocked by required conditions
Tests / Code Coverage / tests (03) (push) Blocked by required conditions
Tests / Code Coverage / test-integration (push) Waiting to run
Tests / Code Coverage / test-e2e (push) Waiting to run
Tests / Code Coverage / repo-analysis (push) Blocked by required conditions
Tests / Code Coverage / test-sim-nondeterminism (push) Waiting to run
Tests / Code Coverage / test-clientv2 (push) Waiting to run
Tests / Code Coverage / test-core (push) Waiting to run
Tests / Code Coverage / test-depinject (push) Waiting to run
Tests / Code Coverage / test-errors (push) Waiting to run
Tests / Code Coverage / test-math (push) Waiting to run
Tests / Code Coverage / test-schema (push) Waiting to run
Tests / Code Coverage / test-collections (push) Waiting to run
Tests / Code Coverage / test-cosmovisor (push) Waiting to run
Tests / Code Coverage / test-confix (push) Waiting to run
Tests / Code Coverage / test-store (push) Waiting to run
Tests / Code Coverage / test-log (push) Waiting to run
Tests / Code Coverage / test-x-tx (push) Waiting to run
Tests / Code Coverage / test-x-nft (push) Waiting to run
Tests / Code Coverage / test-x-circuit (push) Waiting to run
Tests / Code Coverage / test-x-feegrant (push) Waiting to run
Tests / Code Coverage / test-x-evidence (push) Waiting to run
Tests / Code Coverage / test-x-upgrade (push) Waiting to run
Tests / Code Coverage / test-tools-benchmark (push) Waiting to run
refactor: complete sovereign stack cleanup — all github.com upstream refs purged
2026-05-11 03:46:06 +03:00

84 lines
3.2 KiB
Go

package keeper
import (
"bytes"
"fmt"
errorsmod "cosmossdk.io/errors"
"git.cw.tr/mukan-network/mukan-sdk/baseapp"
"git.cw.tr/mukan-network/mukan-sdk/codec"
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
sdkerrors "git.cw.tr/mukan-network/mukan-sdk/types/errors"
"git.cw.tr/mukan-network/mukan-sdk/x/group"
"git.cw.tr/mukan-network/mukan-sdk/x/group/errors"
)
// doExecuteMsgs routes the messages to the registered handlers. Messages are limited to those that require no authZ or
// by the account of group policy only. Otherwise this gives access to other peoples accounts as the sdk middlewares are bypassed
func (s Keeper) doExecuteMsgs(ctx sdk.Context, router baseapp.MessageRouter, proposal group.Proposal, groupPolicyAcc sdk.AccAddress, decisionPolicy group.DecisionPolicy) ([]sdk.Result, error) {
// Ensure it's not too early to execute the messages.
minExecutionDate := proposal.SubmitTime.Add(decisionPolicy.GetMinExecutionPeriod())
if ctx.BlockTime().Before(minExecutionDate) {
return nil, errors.ErrInvalid.Wrapf("must wait until %s to execute proposal %d", minExecutionDate, proposal.Id)
}
// Ensure it's not too late to execute the messages.
// After https://git.cw.tr/mukan-network/mukan-sdk/issues/11245, proposals should
// be pruned automatically, so this function should not even be called, as
// the proposal doesn't exist in state. For sanity check, we can still keep
// this simple and cheap check.
expiryDate := proposal.VotingPeriodEnd.Add(s.config.MaxExecutionPeriod)
if expiryDate.Before(ctx.BlockTime()) {
return nil, errors.ErrExpired.Wrapf("proposal expired on %s", expiryDate)
}
msgs, err := proposal.GetMsgs()
if err != nil {
return nil, err
}
results := make([]sdk.Result, len(msgs))
if err := ensureMsgAuthZ(msgs, groupPolicyAcc, s.cdc); err != nil {
return nil, err
}
for i, msg := range msgs {
handler := s.router.Handler(msg)
if handler == nil {
return nil, errorsmod.Wrapf(errors.ErrInvalid, "no message handler found for %q", sdk.MsgTypeURL(msg))
}
r, err := handler(ctx, msg)
if err != nil {
return nil, errorsmod.Wrapf(err, "message %s at position %d", sdk.MsgTypeURL(msg), i)
}
// Handler should always return non-nil sdk.Result.
if r == nil {
return nil, fmt.Errorf("got nil sdk.Result for message %q at position %d", msg, i)
}
results[i] = *r
}
return results, nil
}
// ensureMsgAuthZ checks that if a message requires signers that all of them
// are equal to the given account address of group policy.
func ensureMsgAuthZ(msgs []sdk.Msg, groupPolicyAcc sdk.AccAddress, cdc codec.Codec) error {
for i := range msgs {
// In practice, GetSigners() should return a non-empty array without
// duplicates, so the code below is equivalent to:
// `msgs[i].GetSigners()[0] == groupPolicyAcc`
// but we prefer to loop through all GetSigners just to be sure.
signers, _, err := cdc.GetMsgV1Signers(msgs[i])
if err != nil {
return err
}
for _, acct := range signers {
if !bytes.Equal(groupPolicyAcc, acct) {
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "msg does not have group policy authorization; expected %s, got %s", groupPolicyAcc.String(), sdk.AccAddress(acct).String())
}
}
}
return nil
}