Skip to content

Commit

Permalink
Add stratgy for indexing cosmwasm MsgExecuteContracts by providing su…
Browse files Browse the repository at this point in the history
…pport for custom message handlers based on contract address or code ID
  • Loading branch information
pharr117 committed Jun 27, 2024
1 parent 9e1ffc6 commit d8146d0
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 8 deletions.
3 changes: 2 additions & 1 deletion cmd/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ func setupIndexer() *Indexer {
// Setup chain specific stuff
core.SetupAddressRegex(indexer.cfg.Lens.AccountPrefix + "(valoper)?1[a-z0-9]{38}")
core.SetupAddressPrefix(indexer.cfg.Lens.AccountPrefix)
core.ChainSpecificMessageTypeHandlerBootstrap(indexer.cfg.Lens.ChainID)
core.ChainSpecificBeginBlockerEventTypeHandlerBootstrap(indexer.cfg.Lens.ChainID)
core.ChainSpecificEndBlockerEventTypeHandlerBootstrap(indexer.cfg.Lens.ChainID)
core.ChainSpecificEpochIdentifierEventTypeHandlersBootstrap(indexer.cfg.Lens.ChainID)
Expand All @@ -121,6 +120,8 @@ func setupIndexer() *Indexer {
tasks.DoChainSpecificUpsertDenoms(indexer.db, indexer.cfg.Lens.ChainID, indexer.cfg.Base.RequestRetryAttempts, indexer.cfg.Base.RequestRetryMaxWait)
indexer.cl = config.GetLensClient(indexer.cfg.Lens)

core.ChainSpecificMessageTypeHandlerBootstrap(indexer.cfg.Lens.ChainID, indexer.cl)

// Depending on the app configuration, wait for the chain to catch up
chainCatchingUp, err := rpc.IsCatchingUp(indexer.cl)
for indexer.cfg.Base.WaitForChain && chainCatchingUp && err == nil {
Expand Down
19 changes: 17 additions & 2 deletions core/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules/staking"
txtypes "github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules/tx"
"github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules/vesting"
"github.com/DefiantLabs/cosmos-tax-cli/cosmwasm"
"github.com/DefiantLabs/cosmos-tax-cli/cosmwasm/modules/wasm"
dbTypes "github.com/DefiantLabs/cosmos-tax-cli/db"
"github.com/DefiantLabs/cosmos-tax-cli/osmosis"
Expand Down Expand Up @@ -159,7 +160,6 @@ var messageTypeIgnorer = map[string]interface{}{
/////// Possible Taxable Events, future work ///////
////////////////////////////////////////////////////
// CosmWasm
wasm.MsgExecuteContract: nil,
wasm.MsgInstantiateContract: nil,
wasm.MsgInstantiateContract2: nil,
wasm.MsgStoreCode: nil,
Expand All @@ -179,18 +179,33 @@ var messageTypeIgnorer = map[string]interface{}{

// Merge the chain specific message type handlers into the core message type handler map.
// Chain specific handlers will be registered BEFORE any generic handlers.
func ChainSpecificMessageTypeHandlerBootstrap(chainID string) {
func ChainSpecificMessageTypeHandlerBootstrap(chainID string, lensClient *client.ChainClient) {
var customContractAddressHandlers []wasm.ContractExecutionMessageHandler
var chainSpecificMessageTpeHandler map[string][]func() txtypes.CosmosMessage
if chainID == osmosis.ChainID {
chainSpecificMessageTpeHandler = osmosis.MessageTypeHandler
}

for key, value := range chainSpecificMessageTpeHandler {
if list, ok := messageTypeHandler[key]; ok {
messageTypeHandler[key] = append(value, list...)
} else {
messageTypeHandler[key] = value
}
}

cosmWasmHandlers, err := cosmwasm.GetCosmWasmMessageTypeHandlers(customContractAddressHandlers, lensClient)
if err != nil {
config.Log.Fatal("Error getting CosmWasm message type handlers.", err)
}

for key, value := range cosmWasmHandlers {
if list, ok := messageTypeHandler[key]; ok {
messageTypeHandler[key] = append(value, list...)
} else {
messageTypeHandler[key] = value
}
}
}

// ParseCosmosMessageJSON - Parse a SINGLE Cosmos Message into the appropriate type.
Expand Down
52 changes: 52 additions & 0 deletions cosmwasm/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cosmwasm

import (
txTypes "github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules/tx"
"github.com/DefiantLabs/cosmos-tax-cli/cosmwasm/modules/wasm"
"github.com/DefiantLabs/cosmos-tax-cli/rpc"
"github.com/DefiantLabs/lens/client"
)

var defaultMessageTypeHandler = map[string][]func() txTypes.CosmosMessage{}

var contractAddressRegistry = map[string]wasm.ContractExecutionMessageHandler{}

func GetCosmWasmMessageTypeHandlers(customContractAddressHandlers []wasm.ContractExecutionMessageHandler, lensClient *client.ChainClient) (map[string][]func() txTypes.CosmosMessage, error) {
msgExecuteContractHandlers, err := configureMsgExecuteContractHandler(customContractAddressHandlers, lensClient)
if err != nil {
return nil, err
}

defaultMessageTypeHandler[wasm.MsgExecuteContract] = msgExecuteContractHandlers

return defaultMessageTypeHandler, nil
}

// Configures a handler wrapper that will allow using registry values to find custom message handlers
func configureMsgExecuteContractHandler(customContractAddressHandlers []wasm.ContractExecutionMessageHandler, lensClient *client.ChainClient) ([]func() txTypes.CosmosMessage, error) {
for _, handler := range customContractAddressHandlers {
if castHandler, ok := handler.(wasm.ContractExecutionMessageHandlerByContractAddress); ok {
contractAddressRegistry[castHandler.ContractAddress()] = handler
} else if castHandler, ok := handler.(wasm.ContractExecutionMessageHandlerByCodeID); ok {
// Query for code ID contract addresses using wasm querying
resp, err := rpc.GetContractsByCodeIDAtHeight(lensClient, castHandler.CodeID(), 0)
if err != nil {
return nil, err
}

for _, contractAddress := range resp.Contracts {
contractAddressRegistry[contractAddress] = handler
}
}
}

configuredExecuteContractWrapper := wasm.WrapperMsgExecuteContract{
ContractAddressRegistry: contractAddressRegistry,
}

return []func() txTypes.CosmosMessage{
func() txTypes.CosmosMessage {
return configuredExecuteContractWrapper
},
}, nil
}
66 changes: 66 additions & 0 deletions cosmwasm/modules/wasm/types.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package wasm

import (
"fmt"

wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types"
parsingTypes "github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules"
txTypes "github.com/DefiantLabs/cosmos-tax-cli/cosmos/modules/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
)

const (
MsgExecuteContract = "/cosmwasm.wasm.v1.MsgExecuteContract"
MsgInstantiateContract = "/cosmwasm.wasm.v1.MsgInstantiateContract"
Expand All @@ -18,3 +27,60 @@ const (
MsgAddCodeUploadParamsAddresses = "/cosmwasm.wasm.v1.MsgAddCodeUploadParamsAddresses"
MsgStoreAndMigrateContract = "/cosmwasm.wasm.v1.MsgStoreAndMigrateContract"
)

type ContractExecutionMessageHandler interface {
txTypes.CosmosMessage
ContractFriendlyName() string
TopLevelFieldIdentifiers() []string
TopLevelIdentifierType() any
CosmosMessageType() txTypes.CosmosMessage
}

type ContractExecutionMessageHandlerByCodeID interface {
ContractExecutionMessageHandler
CodeID() uint64
}

type ContractExecutionMessageHandlerByContractAddress interface {
ContractExecutionMessageHandler
ContractAddress() string
}

type WrapperMsgExecuteContract struct {
txTypes.Message
CosmosMsgExecuteContract *wasmTypes.MsgExecuteContract
ContractAddressRegistry map[string]ContractExecutionMessageHandler
CurrentHandler ContractExecutionMessageHandler
ContractAddress string
}

func (w WrapperMsgExecuteContract) HandleMsg(typeURL string, msg sdk.Msg, log *txTypes.LogMessage) error {
w.Type = typeURL
w.CosmosMsgExecuteContract = msg.(*wasmTypes.MsgExecuteContract)

if handler, ok := w.ContractAddressRegistry[w.CosmosMsgExecuteContract.Contract]; ok {
w.CurrentHandler = handler
return w.CurrentHandler.HandleMsg(typeURL, msg, log)
}

return nil
}

func (w WrapperMsgExecuteContract) ParseRelevantData() []parsingTypes.MessageRelevantInformation {
if w.CurrentHandler != nil {
return w.CurrentHandler.ParseRelevantData()
}

return nil
}

func (w WrapperMsgExecuteContract) GetType() string {
return MsgExecuteContract
}

func (w WrapperMsgExecuteContract) String() string {
if w.CurrentHandler != nil {
return w.CurrentHandler.String()
}
return fmt.Sprintf("MsgExecuteContract: No handler found for contract address %s", w.ContractAddress)
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ toolchain go1.21.11

require (
github.com/BurntSushi/toml v1.3.2
// Our lens library is pinned to this specific SHA and branch: 7732945f81598e4d6aff47e0d4ca81b0ec26d8b3, https://github.com/DefiantLabs/lens/tree/v0.0.21-dl
github.com/DefiantLabs/lens v0.3.1-0.20240626071018-7732945f8159
// Our lens library is pinned to this specific SHA and branch: 2ff2d8138af66fb3f3e3429b9837db1e720ed39f, https://github.com/DefiantLabs/lens/tree/v0.0.22-dl
github.com/DefiantLabs/lens v0.3.1-0.20240627235205-2ff2d8138af6
github.com/cosmos/cosmos-sdk v0.47.8
github.com/gin-gonic/gin v1.9.1
github.com/go-co-op/gocron v1.13.0
Expand All @@ -26,6 +26,7 @@ require (

require (
cosmossdk.io/math v1.3.0
github.com/CosmWasm/wasmd v0.45.1-0.20231128163306-4b9b61faeaa3
github.com/cometbft/cometbft v0.38.0
github.com/cosmos/ibc-go/v7 v7.4.1
github.com/go-git/go-git/v5 v5.11.0
Expand Down Expand Up @@ -53,7 +54,6 @@ require (
dario.cat/mergo v1.0.0 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/keyring v1.2.1 // indirect
github.com/CosmWasm/wasmd v0.45.1-0.20231128163306-4b9b61faeaa3 // indirect
github.com/CosmWasm/wasmvm v1.5.2 // indirect
github.com/DataDog/zstd v1.5.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,8 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/DefiantLabs/lens v0.3.1-0.20240626071018-7732945f8159 h1:GB/lSc4/UT7M64scdyh0lrwyRRi3UyCto9RvwJekVKI=
github.com/DefiantLabs/lens v0.3.1-0.20240626071018-7732945f8159/go.mod h1:nTPf+NQkhPH6NcBY5p0lpdb14WPiZOeMZDDkq1IWl30=
github.com/DefiantLabs/lens v0.3.1-0.20240627235205-2ff2d8138af6 h1:n1wKVmFX2hUfL3B+PDbPrEbYAD47hNdNUQOnyPn32TE=
github.com/DefiantLabs/lens v0.3.1-0.20240627235205-2ff2d8138af6/go.mod h1:nTPf+NQkhPH6NcBY5p0lpdb14WPiZOeMZDDkq1IWl30=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
Expand Down
12 changes: 12 additions & 0 deletions rpc/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
osmosisProtorev "github.com/osmosis-labs/osmosis/v25/x/protorev/types"
osmosisEpochs "github.com/osmosis-labs/osmosis/x/epochs/types"

wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types"
"github.com/DefiantLabs/cosmos-tax-cli/config"
lensClient "github.com/DefiantLabs/lens/client"
lensQuery "github.com/DefiantLabs/lens/client/query"
Expand Down Expand Up @@ -193,3 +194,14 @@ func GetProtorevDeveloperAccount(cl *lensClient.ChainClient) (*osmosisProtorev.Q
resp, err := query.ProtorevDeveloperAccount()
return resp, err
}

func GetContractsByCodeIDAtHeight(cl *lensClient.ChainClient, codeID uint64, height int64) (*wasmTypes.QueryContractsByCodeResponse, error) {
pg := query.PageRequest{Limit: 100}
options := lensQuery.QueryOptions{Height: height, Pagination: &pg}
query := lensQuery.Query{Client: cl, Options: &options}
resp, err := query.ContractsByCodeIDAtHeight(codeID, height)
if err != nil {
return nil, err
}
return resp, nil
}

0 comments on commit d8146d0

Please sign in to comment.