diff --git a/plugins/indexing/group/module.go b/plugins/indexing/group/module.go new file mode 100644 index 00000000..65749828 --- /dev/null +++ b/plugins/indexing/group/module.go @@ -0,0 +1,175 @@ +package group + +import ( + "bytes" + "encoding/json" + "fmt" + + storetypes "cosmossdk.io/store/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/group" + groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper" + + "github.com/sedaprotocol/seda-chain/plugins/indexing/log" + "github.com/sedaprotocol/seda-chain/plugins/indexing/types" +) + +const StoreKey = group.StoreKey + +type Info group.GroupInfo + +func (p Info) MarshalJSON() ([]byte, error) { + return types.MarshalJSJSON(p) +} + +type Member group.GroupMember + +func (p Member) MarshalJSON() ([]byte, error) { + return types.MarshalJSJSON(p) +} + +func ExtractUpdate(ctx *types.BlockContext, cdc codec.Codec, logger *log.Logger, change *storetypes.StoreKVPair) (*types.Message, error) { + logger.Debug("extracting group update", "change", change) + + if _, found := bytes.CutPrefix(change.Key, []byte{groupkeeper.GroupTablePrefix, 0}); found { + var groupInfo group.GroupInfo + err := cdc.Unmarshal(change.Value, &groupInfo) + if err != nil { + return nil, err + } + + return types.NewMessage("group-info", Info(groupInfo), ctx), nil + } else if keyBytes, found := bytes.CutPrefix(change.Key, []byte{groupkeeper.GroupMemberTablePrefix, 0}); found { + if change.Delete { + groupID := storetypes.BigEndianToUint64(keyBytes[:8]) + err := sdk.VerifyAddressFormat(keyBytes[8:]) + if err != nil { + return nil, err + } + data := struct { + GroupID string `json:"groupID"` + MemberAddress string `json:"memberAddress"` + }{ + GroupID: fmt.Sprintf("%d", groupID), + MemberAddress: sdk.AccAddress(keyBytes[8:]).String(), + } + + return types.NewMessage("group-member-delete", data, ctx), nil + } + + var member group.GroupMember + err := cdc.Unmarshal(change.Value, &member) + if err != nil { + return nil, err + } + + return types.NewMessage("group-member", Member(member), ctx), nil + } else if _, found := bytes.CutPrefix(change.Key, []byte{groupkeeper.GroupPolicyTablePrefix, 0}); found { + if change.Delete { + logger.Trace("skipping group-policy delete", "change", change) + return nil, nil + } + + var policy group.GroupPolicyInfo + err := cdc.Unmarshal(change.Value, &policy) + if err != nil { + return nil, err + } + + var decisionPolicy json.RawMessage + if policy.DecisionPolicy != nil { + policyJSON, err := cdc.MarshalJSON(policy.DecisionPolicy) + if err != nil { + // Fallback to just type URL if marshaling fails + decisionPolicy = json.RawMessage(fmt.Sprintf(`{"@type":"%s"}`, policy.DecisionPolicy.GetTypeUrl())) + } else { + decisionPolicy = policyJSON + } + } + + data := struct { + Address string `json:"address"` + GroupID uint64 `json:"group_id"` + Admin string `json:"admin"` + Metadata string `json:"metadata"` + Version uint64 `json:"version"` + DecisionPolicy json.RawMessage `json:"decision_policy,omitempty"` + CreatedAt string `json:"created_at"` + }{ + Address: policy.Address, + GroupID: policy.GroupId, + Admin: policy.Admin, + Metadata: policy.Metadata, + Version: policy.Version, + DecisionPolicy: decisionPolicy, + CreatedAt: policy.CreatedAt.String(), + } + + return types.NewMessage("group-policy", data, ctx), nil + } else if keyBytes, found := bytes.CutPrefix(change.Key, []byte{groupkeeper.ProposalTablePrefix, 0}); found { + if change.Delete { + proposalID := storetypes.BigEndianToUint64(keyBytes[:8]) + + data := struct { + ProposalID string `json:"proposalID"` + }{ + ProposalID: fmt.Sprintf("%d", proposalID), + } + + return types.NewMessage("group-proposal-delete", data, ctx), nil + } + + var proposal group.Proposal + err := cdc.Unmarshal(change.Value, &proposal) + if err != nil { + return nil, err + } + + messages := make([]json.RawMessage, len(proposal.Messages)) + for i, msg := range proposal.Messages { + msgJSON, err := cdc.MarshalJSON(msg) + if err != nil { + // Fallback to just type URL if marshaling fails + messages[i] = json.RawMessage(fmt.Sprintf(`{"@type":"%s"}`, msg.GetTypeUrl())) + } else { + messages[i] = msgJSON + } + } + + data := struct { + ID uint64 `json:"id"` + GroupPolicyAddress string `json:"group_policy_address"` + Metadata string `json:"metadata"` + Proposers []string `json:"proposers"` + SubmitTime string `json:"submit_time"` + GroupVersion uint64 `json:"group_version"` + GroupPolicyVersion uint64 `json:"group_policy_version"` + Status string `json:"status"` + VotingPeriodEnd string `json:"voting_period_end"` + ExecutorResult string `json:"executor_result"` + Title string `json:"title"` + Summary string `json:"summary"` + Messages []json.RawMessage `json:"messages"` + }{ + ID: proposal.Id, + GroupPolicyAddress: proposal.GroupPolicyAddress, + Metadata: proposal.Metadata, + Proposers: proposal.Proposers, + SubmitTime: proposal.SubmitTime.String(), + GroupVersion: proposal.GroupVersion, + GroupPolicyVersion: proposal.GroupPolicyVersion, + Status: proposal.Status.String(), + VotingPeriodEnd: proposal.VotingPeriodEnd.String(), + ExecutorResult: proposal.ExecutorResult.String(), + Title: proposal.Title, + Summary: proposal.Summary, + Messages: messages, + } + + return types.NewMessage("group-proposal", data, ctx), nil + } + logger.Trace("skipping change", "change", change) + return nil, nil +} diff --git a/plugins/indexing/plugin.go b/plugins/indexing/plugin.go index c6299fed..583b99cb 100644 --- a/plugins/indexing/plugin.go +++ b/plugins/indexing/plugin.go @@ -40,7 +40,7 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" govtypesv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - "github.com/cosmos/cosmos-sdk/x/group" + groupmodule "github.com/cosmos/cosmos-sdk/x/group" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" @@ -50,6 +50,7 @@ import ( "github.com/sedaprotocol/seda-chain/plugins/indexing/base" "github.com/sedaprotocol/seda-chain/plugins/indexing/batching" dataproxy "github.com/sedaprotocol/seda-chain/plugins/indexing/data-proxy" + "github.com/sedaprotocol/seda-chain/plugins/indexing/group" "github.com/sedaprotocol/seda-chain/plugins/indexing/log" oracleprogram "github.com/sedaprotocol/seda-chain/plugins/indexing/oracle-program" "github.com/sedaprotocol/seda-chain/plugins/indexing/pluginaws" @@ -139,6 +140,8 @@ func (p *IndexerPlugin) extractUpdate(change *storetypes.StoreKVPair) (*types.Me return oracleprogram.ExtractUpdate(p.block, p.cdc, p.logger, change) case tally.StoreKey: return tally.ExtractUpdate(p.block, p.cdc, p.logger, change) + case group.StoreKey: + return group.ExtractUpdate(p.block, p.cdc, p.logger, change) default: return nil, nil } @@ -213,7 +216,7 @@ func main() { vestingtypes.RegisterInterfaces(interfaceRegistry) banktypes.RegisterInterfaces(interfaceRegistry) feegrant.RegisterInterfaces(interfaceRegistry) - group.RegisterInterfaces(interfaceRegistry) + groupmodule.RegisterInterfaces(interfaceRegistry) govtypesv1.RegisterInterfaces(interfaceRegistry) govtypesv1beta1.RegisterInterfaces(interfaceRegistry) minttypes.RegisterInterfaces(interfaceRegistry) diff --git a/testutil/contract_msgs.go b/testutil/contract_msgs.go index 381cf922..65bdb9d5 100644 --- a/testutil/contract_msgs.go +++ b/testutil/contract_msgs.go @@ -19,7 +19,7 @@ func CommitMsg(drID, commitment, stakerPubKey, proof string, gasUsed uint64) []b } func RevealMsg(drID, reveal, stakerPubKey, proof string, proxyPubKeys []string, exitCode byte, drHeight, gasUsed uint64) []byte { - quotedObjects := []string{} + quotedObjects := make([]string, 0, len(proxyPubKeys)) for _, obj := range proxyPubKeys { quotedObjects = append(quotedObjects, fmt.Sprintf("%q", obj)) } diff --git a/x/batching/types/data_result.go b/x/batching/types/data_result.go index e2c768bd..87110f9c 100644 --- a/x/batching/types/data_result.go +++ b/x/batching/types/data_result.go @@ -64,7 +64,7 @@ func (dr *DataResult) TryHash() (string, error) { sedaPayloadHash := hasher.Sum(nil) hasher.Reset() - var allBytes []byte + allBytes := make([]byte, 0, len(versionHash)+len(drIDBytes)+1+1+len(resultHash)+len(blockHeightBytes)+len(blockTimestampBytes)+len(gasUsedBytes)+len(paybackAddrHash)+len(sedaPayloadHash)) allBytes = append(allBytes, versionHash...) allBytes = append(allBytes, drIDBytes...) allBytes = append(allBytes, consensusByte) diff --git a/x/tally/keeper/gas_meter.go b/x/tally/keeper/gas_meter.go index 38ada84d..2d3c2d2a 100644 --- a/x/tally/keeper/gas_meter.go +++ b/x/tally/keeper/gas_meter.go @@ -18,7 +18,9 @@ import ( // sent to the core contract based on the given gas meter. It takes the ID and // the height of the request for event emission. func (k Keeper) DistributionsFromGasMeter(ctx sdk.Context, reqID string, reqHeight uint64, gasMeter *types.GasMeter, burnRatio math.LegacyDec) []types.Distribution { + //nolint:prealloc // TODO: To be addressed in the future dists := []types.Distribution{} + //nolint:prealloc // TODO: To be addressed in the future attrs := []sdk.Attribute{ sdk.NewAttribute(types.AttributeDataRequestID, reqID), sdk.NewAttribute(types.AttributeDataRequestHeight, strconv.FormatUint(reqHeight, 10)),