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

Problem: MsgExec may squeeze multiple message events into a single one #732

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions usecase/parser/inner_msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package parser

import (
"fmt"

"github.com/crypto-com/chain-indexing/usecase/model"
"github.com/crypto-com/chain-indexing/usecase/parser/utils"
)

func ParseTxsResultsEvents(
msgs []interface{},
logs []model.BlockResultsTxsResultLog,
) []model.BlockResultsTxsResultLog {
var resultLog []model.BlockResultsTxsResultLog
var parsedEvents *utils.ParsedTxsResultsEvents

if len(msgs) == len(logs) || len(logs) <= 0 {
return logs
}
log := logs[0]
parsedEvents = utils.NewParsedTxsResultsEvents(log.Events)

for innerMsgIndex, innerMsgInterface := range msgs {
innerMsg, ok := innerMsgInterface.(map[string]interface{})
if !ok {
panic(fmt.Errorf("error parsing MsgExec.msgs[%v] to map[string]interface{}: %v", innerMsgIndex, innerMsgInterface))
}

innerMsgType, ok := innerMsg["@type"].(string)
if !ok {
panic(fmt.Errorf("error missing '@type' in MsgExec.msgs[%v]: %v", innerMsgIndex, innerMsg))
}

validateEvents := ParseInnerMsgsEvents(innerMsgType, innerMsgIndex, parsedEvents)

log := model.BlockResultsTxsResultLog{
MsgIndex: innerMsgIndex,
Events: validateEvents,
}
resultLog = append(resultLog, log)
}

return resultLog
}

func ParseInnerMsgsEvents(
innerMsgType string,
innerMsgIndex int,
parsedEvents *utils.ParsedTxsResultsEvents,
) []model.BlockResultsEvent {
var extractedEvents []model.BlockResultsEvent
switch innerMsgType {

// bank
case "/cosmos.bank.v1beta1.MsgSend":
extractedEvents = MsgSend(parsedEvents, innerMsgIndex)

// distribution
case "/cosmos.distribution.v1beta1.MsgSetWithdrawAddress":
extractedEvents = MsgSetWithdrawAddress(parsedEvents, innerMsgIndex)
case "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward":
extractedEvents = MsgWithdrawDelegatorReward(parsedEvents, innerMsgIndex)
case "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission":
extractedEvents = MsgWithdrawValidatorCommission(parsedEvents, innerMsgIndex)
case "/cosmos.distribution.v1beta1.MsgFundCommunityPool":
extractedEvents = MsgFundCommunityPool(parsedEvents, innerMsgIndex)
}

return extractedEvents
}

func MsgSend(parsedEvents *utils.ParsedTxsResultsEvents,
innerMsgIndex int,
) []model.BlockResultsEvent {
eventTypes := []string{"coin_spent", "coin_received", "transfer", "message"}

return extract(innerMsgIndex, eventTypes, []string{}, parsedEvents)
}

func MsgSetWithdrawAddress(parsedEvents *utils.ParsedTxsResultsEvents,
innerMsgIndex int,
) []model.BlockResultsEvent {
eventTypes := []string{"set_withdraw_address", "message"}

return extract(innerMsgIndex, eventTypes, []string{}, parsedEvents)
}

func MsgWithdrawDelegatorReward(parsedEvents *utils.ParsedTxsResultsEvents,
innerMsgIndex int,
) []model.BlockResultsEvent {
eventTypes := []string{"coin_spent", "coin_received", "transfer", "message", "withdraw_rewards"}

eventTypesNoTransfer := []string{
"message",
"withdraw_rewards",
}
return extract(innerMsgIndex, eventTypes, eventTypesNoTransfer, parsedEvents)
}

func MsgWithdrawValidatorCommission(parsedEvents *utils.ParsedTxsResultsEvents,
innerMsgIndex int,
) []model.BlockResultsEvent {
eventTypes := []string{"coin_spent", "coin_received", "transfer", "message", "withdraw_commission"}

eventTypesNoTransfer := []string{"message", "withdraw_commission"}

return extract(innerMsgIndex, eventTypes, eventTypesNoTransfer, parsedEvents)
}

func MsgFundCommunityPool(parsedEvents *utils.ParsedTxsResultsEvents,
innerMsgIndex int,
) []model.BlockResultsEvent {
eventTypes := []string{"coin_spent", "coin_received", "transfer", "message"}

eventTypesNoTransfer := []string{"message"}

return extract(innerMsgIndex, eventTypes, eventTypesNoTransfer, parsedEvents)
}

func extract(innerMsgIndex int, eventTypes []string, eventTypesRetry []string, parsedEvents *utils.ParsedTxsResultsEvents) []model.BlockResultsEvent {
// extract events
extractedEvents := getMsgEvents(innerMsgIndex, eventTypes, parsedEvents)

// retry
if len(extractedEvents) <= 0 {
extractedEvents = getMsgEvents(innerMsgIndex, eventTypesRetry, parsedEvents)
}

return extractedEvents
}

func getMsgEvents(innerMsgIndex int, eventTypes []string, parsedEvents *utils.ParsedTxsResultsEvents) []model.BlockResultsEvent {
var extractedEvents []model.BlockResultsEvent

for _, eventType := range eventTypes {

events := parsedEvents.GetRawEvents()

for _, event := range events {
splitBykey := utils.NewParsedTxsResultLogEventsSplitByKey(&event)

rawEvent := splitBykey[innerMsgIndex].GetRawEvents()
keyIndex := splitBykey[innerMsgIndex].GetKeyIndex()

var extractedAttributes model.BlockResultsEvent

for _, key := range keyIndex {
extractedAttributes.Type = rawEvent.Type
extractedAttributes.Attributes = append(extractedAttributes.Attributes, rawEvent.Attributes[key])
}

// check attribute key
if rawEvent.Type == eventType {
extractedEvents = append(extractedEvents, extractedAttributes)

}
}
}

return extractedEvents
}
78 changes: 74 additions & 4 deletions usecase/parser/msg.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package parser

import (
"encoding/json"
"fmt"
"strconv"
"time"
Expand Down Expand Up @@ -121,15 +122,17 @@ func ParseBlockTxsMsgToCommands(
// cosmos authz
"/cosmos.authz.v1beta1.MsgGrant",
"/cosmos.authz.v1beta1.MsgRevoke",
// FIXME: https://github.com/crypto-com/chain-indexing/issues/673
//"/cosmos.authz.v1beta1.MsgExec",
"/cosmos.authz.v1beta1.MsgExec",

// cosmos feegrant
"/cosmos.feegrant.v1beta1.MsgGrantAllowance",
"/cosmos.feegrant.v1beta1.MsgRevokeAllowance",

// cosmos vesting
"/cosmos.vesting.v1beta1.MsgCreateVestingAccount":
"/cosmos.vesting.v1beta1.MsgCreateVestingAccount",

// ethermint evm
"/ethermint.evm.v1.MsgEthereumTx":
parser := parserManager.GetParser(utils.CosmosParserKey(msgType.(string)), utils.ParserBlockHeight(blockHeight))

msgCommands, possibleSignerAddresses = parser(utils.CosmosParserParams{
Expand Down Expand Up @@ -1615,6 +1618,14 @@ func parseMsgExecInnerMsgs(
panic(fmt.Errorf("error parsing MsgExec.msgs to []interface{}: %v", parserParams.Msg["msgs"]))
}

// group event by message type
if len(msgs) > 1 {
parserParams.TxsResult.Log = ParseTxsResultsEvents(msgs, parserParams.TxsResult.Log)
bytes, _ := json.Marshal(parserParams.TxsResult.Log)
rawLog, _ := json.Marshal(bytes)
parserParams.TxsResult.RawLog = string(rawLog)
}

for innerMsgIndex, innerMsgInterface := range msgs {
innerMsg, ok := innerMsgInterface.(map[string]interface{})
if !ok {
Expand All @@ -1628,13 +1639,15 @@ func parseMsgExecInnerMsgs(

parser := parserParams.ParserManager.GetParser(utils.CosmosParserKey(innerMsgType), utils.ParserBlockHeight(blockHeight))

parserParams.MsgCommonParams.MsgIndex = innerMsgIndex

msgCommands, _ := parser(utils.CosmosParserParams{
AddressPrefix: parserParams.AddressPrefix,
StakingDenom: parserParams.StakingDenom,
TxsResult: parserParams.TxsResult,
MsgCommonParams: parserParams.MsgCommonParams,
Msg: innerMsg,
MsgIndex: parserParams.MsgIndex,
MsgIndex: innerMsgIndex,
ParserManager: parserParams.ParserManager,
})
commands = append(commands, msgCommands...)
Expand Down Expand Up @@ -1959,3 +1972,60 @@ func ParseMsgCreateVestingAccount(
msgCreateVestingAccountParams,
)}, possibleSignerAddresses
}

func ParseMsgEthereumTx(
parserParams utils.CosmosParserParams,
) ([]command.Command, []string) {
var rawMsg model.RawMsgEthereumTx
decoderConfig := &mapstructure.DecoderConfig{
WeaklyTypedInput: true,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToTimeHookFunc(time.RFC3339),
mapstructure_utils.StringToDurationHookFunc(),
mapstructure_utils.StringToByteSliceHookFunc(),
),
Result: &rawMsg,
}
decoder, decoderErr := mapstructure.NewDecoder(decoderConfig)
if decoderErr != nil {
panic(fmt.Errorf("error creating RawMsgEthereumTx decoder: %v", decoderErr))
}
if err := decoder.Decode(parserParams.Msg); err != nil {
panic(fmt.Errorf("error decoding RawMsgEthereumTx: %v", err))
}

if !parserParams.MsgCommonParams.TxSuccess {
// FIXME: https://github.com/crypto-com/chain-indexing/issues/730
msgEthereumTxParams := model.MsgEthereumTxParams{
RawMsgEthereumTx: rawMsg,
}

// Getting possible signer address from Msg
var possibleSignerAddresses []string
// FIXME: https://github.com/crypto-com/chain-indexing/issues/729
// possibleSignerAddresses = append(possibleSignerAddresses, msgEthereumTxParams.From)

return []command.Command{command_usecase.NewCreateMsgEthereumTx(
parserParams.MsgCommonParams,

msgEthereumTxParams,
)}, possibleSignerAddresses
}

// FIXME: https://github.com/crypto-com/chain-indexing/issues/730
msgEthereumTxParams := model.MsgEthereumTxParams{
RawMsgEthereumTx: rawMsg,
}

// Getting possible signer address from Msg
var possibleSignerAddresses []string
// FIXME: https://github.com/crypto-com/chain-indexing/issues/729
// possibleSignerAddresses = append(possibleSignerAddresses, msgEthereumTxParams.From)

return []command.Command{command_usecase.NewCreateMsgEthereumTx(
parserParams.MsgCommonParams,

msgEthereumTxParams,
)}, possibleSignerAddresses
}
Loading