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 #737

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
175 changes: 175 additions & 0 deletions usecase/parser/inner_msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package parser

import (
"fmt"

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

func ParseTxsResultsEvents(
innerMsgIndex int,
innerMsg map[string]interface{},
logs model.BlockResultsTxsResultLog,
) []model.BlockResultsTxsResultLog {
var resultLog []model.BlockResultsTxsResultLog

// parse events with index
parsedEvents := utils.NewParsedTxsResultsEvents(logs.Events)
extractedEvents := ParseInnerMsgsEvents(innerMsg, innerMsgIndex, parsedEvents)

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

return resultLog
}

func ParseInnerMsgsEvents(
innerMsg map[string]interface{},
innerMsgIndex int,
parsedEvents *utils.ParsedTxsResultsEvents,
) []model.BlockResultsEvent {
var extractedEvents []model.BlockResultsEvent

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

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

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

// cosmos staking
case "/cosmos.staking.v1beta1.MsgDelegate":
extractedEvents = MsgDelegate(innerMsgIndex, innerMsg, parsedEvents)
// case "/cosmos.staking.v1beta1.MsgUndelegate":
// extractedEvents = MsgUndelegate(innerMsgIndex, innerMsg, parsedEvents)
// case "/cosmos.staking.v1beta1.MsgBeginRedelegate":
// extractedEvents = MsgBeginRedelegate(innerMsgIndex, innerMsg, parsedEvents)
}

return extractedEvents
}

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

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

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

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

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

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

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

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

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

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

eventTypesNoTransfer := []string{"message"}

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

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

eventTypesNoTransfer := []string{"coin_spent", "coin_received", "delegate", "message"}

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

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

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

return extractedEvents
}

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

for _, eventType := range eventTypes {

events := parsedEvents.GetRawEvents()

for i := range events {
splitBykey := utils.NewParsedTxsResultLogEventsSplitByKey(&events[i])

if len(splitBykey)-1 >= innerMsgIndex {

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

var extractedAttributes model.BlockResultsEvent

// check event amount with inner msg amount
amount := splitBykey[innerMsgIndex].GetAttributeByKey("amount")
if amount == nil {
continue
}

innerMsgAmount, ok := innerMsg["amount"].(string)
if ok && *amount != innerMsgAmount {
continue
}

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
}
61 changes: 48 additions & 13 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,8 +122,7 @@ 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",
Expand Down Expand Up @@ -259,6 +259,7 @@ func ParseMsgWithdrawDelegatorReward(
},
)}, possibleSignerAddresses
}

log := utils.NewParsedTxsResultLog(&parserParams.TxsResult.Log[parserParams.MsgIndex])
var recipient string
var amount coin.Coins
Expand Down Expand Up @@ -1618,7 +1619,10 @@ func parseMsgExecInnerMsgs(
panic(fmt.Errorf("error parsing MsgExec.msgs to []interface{}: %v", parserParams.Msg["msgs"]))
}

txLog := parserParams.TxsResult.Log

for innerMsgIndex, innerMsgInterface := range msgs {
parserParams.TxsResult.Log = txLog
innerMsg, ok := innerMsgInterface.(map[string]interface{})
if !ok {
panic(fmt.Errorf("error parsing MsgExec.msgs[%v] to map[string]interface{}: %v", innerMsgIndex, innerMsgInterface))
Expand All @@ -1629,18 +1633,49 @@ func parseMsgExecInnerMsgs(
panic(fmt.Errorf("error missing '@type' in MsgExec.msgs[%v]: %v", innerMsgIndex, innerMsg))
}

parser := parserParams.ParserManager.GetParser(utils.CosmosParserKey(innerMsgType), utils.ParserBlockHeight(blockHeight))
// skip ParseTxsResultsEvents for inner MsgExec
if innerMsgType == "/cosmos.authz.v1beta1.MsgExec" {
_, ok := innerMsg["msgs"].([]interface{})
if !ok {
panic(fmt.Errorf("error parsing innerMsgExec.msgs.msgs to []interface{}: %v", innerMsg["msgs"]))
}

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

msgCommands, _ := parser(utils.CosmosParserParams{
AddressPrefix: parserParams.AddressPrefix,
StakingDenom: parserParams.StakingDenom,
TxsResult: parserParams.TxsResult,
MsgCommonParams: parserParams.MsgCommonParams,
Msg: innerMsg,
MsgIndex: innerMsgIndex,
ParserManager: parserParams.ParserManager,
})
commands = append(commands, msgCommands...)

msgCommands, _ := parser(utils.CosmosParserParams{
AddressPrefix: parserParams.AddressPrefix,
StakingDenom: parserParams.StakingDenom,
TxsResult: parserParams.TxsResult,
MsgCommonParams: parserParams.MsgCommonParams,
Msg: innerMsg,
MsgIndex: parserParams.MsgIndex,
ParserManager: parserParams.ParserManager,
})
commands = append(commands, msgCommands...)
} else {
parser := parserParams.ParserManager.GetParser(utils.CosmosParserKey(innerMsgType), utils.ParserBlockHeight(blockHeight))

if len(parserParams.TxsResult.Log) > 0 {
// parse events by msg type
parserParams.TxsResult.Log = ParseTxsResultsEvents(innerMsgIndex, innerMsg, parserParams.TxsResult.Log[parserParams.MsgCommonParams.MsgIndex])
bytes, _ := json.Marshal(parserParams.TxsResult.Log)
rawLog, _ := json.Marshal(bytes)
parserParams.TxsResult.RawLog = string(rawLog)
}

msgCommands, _ := parser(utils.CosmosParserParams{
AddressPrefix: parserParams.AddressPrefix,
StakingDenom: parserParams.StakingDenom,
TxsResult: parserParams.TxsResult,
MsgCommonParams: parserParams.MsgCommonParams,
Msg: innerMsg,
MsgIndex: 0,
ParserManager: parserParams.ParserManager,
})
commands = append(commands, msgCommands...)
}
}

return commands
Expand Down
Loading