Skip to content

Cosmos SDK and chain Package Inclusion and Versioning

pharr117 edited this page Mar 29, 2023 · 2 revisions

The application makes use of the Cosmos SDK and various modules developed in Osmosis to support indexing the blockchain transactions found there.

Overview

At its most basic, the application uses the actual types and interfaces provided in the blockchain code to parse out the data received from the nodes for each transaction. We turn the data provided by the node into the actual message types found in the blockchain code. This allows the application to use the actual message as it is represented in the code.

Implications

There are a few implications for this that are important to know:

  1. The application must be provided the packages that correspond to the blockchain messages being indexed
  2. These packages must have the correct interface definitions based on the message type being parsed
  3. As blockchains update their modules, either deprecating old message types or introducing new ones, the application will need to be updated to support these module updates

Updating the Application for New or Deprecated Types

Depending on whether a new message type is added or an old one is deprecated, the application will need to be updated to support these changes.

New Message Type is Added

When a new message type is added, we need to do the following:

  1. Update the package that supports this type to the latest version
  2. Build the parser to support this new type

For example, say Osmosis releases v15 with a new message type we need to parse, but our application includes Osmosis v14.

We would need to update our application's Osmosis version and build the parser to support this new message type.

Old Message Type is Deprecated

Chain developers sometimes remove old message types as they are deprecated. Unfortunately, this does not remove the messages from the node since they are written into old state.

This makes it particularly difficult for the application to handle missing message types. Without the type in the code, we cannot parse the message into its underlying type and we cannot support the message.

We handle this by:

  1. Finding the old message definition codec in the old version of the chain code
  2. Include this message definition codec in our fork of Lens so that Lens can figure out how to handle the type.

This allows Lens to handle old types internally instead of trying to rely on chain developers to always include their old message definitions.

Further Support

The above 2 instances have some serious implications that need to be understood. With the fast-paced nature of some of these blockchain codebases, we will need to be on top of the module changes introduced in order to support new versions.

Sometimes chain developers will, when releasing a new version, introduce new types and deprecate old types at the same time. That means both methods above will have to happen at once.

Deep Dive

Every message in the Cosmos SDK must satisfy the Msg interface. Messages are "module-specific objects that trigger state transitions within the scope of the module they belong to."

We use this to our application's advantage by:

  1. Taking the raw Message in Msg received from the block processor
  2. Figuring out the actual type of the Message
  3. Passing the Msg to a custom-built parser for that message type
  4. Turning the Msg into its actual Message type
  5. Using that type during Message parsing

An Example: MsgMultiSend

As a simple example, take our support for the base Cosmos SDK message type /cosmos.bank.v1beta1.MsgMultiSend. Lets dive into the lifecycle of a transaction that includes this message.

Block Processor

For Block N, our block processor gathers the full list of transactions. These transactions include a list of messages, all of the base Msg type.

Each of the transactions in the block get passed to our Transaction Processor.

Transaction Processor

When a transaction reaches the transaction processor function, we loop through each of the messages in the transaction.

For each message, the application:

  1. Gets the message type string
  2. Finds the appropriate handler function for the message type
  3. Passes the raw Msg value to the handler parser function for processing

Cosmos MsgMultiSend Parser

Source found here.

In the code found above, the application does the following:

  1. Casts the raw Msg into the actual message type and stores that in our interface for later
sf.CosmosMsgMultiSend = msg.(*bankTypes.MsgMultiSend)
  1. Uses the actual code provided by the Cosmos bank module to parse out the required data. In the below code block, the application uses the MsgMultiSend.Inputs variable to pull the Sent coins out of the message.
for _, input := range sf.CosmosMsgMultiSend.Inputs {
    for _, coin := range input.Coins {
        if currentTotal, ok := sentMap[coin.Denom]; ok {
            sentMap[coin.Denom] = currentTotal.Add(coin.Amount)
        } else {
            sentMap[coin.Denom] = coin.Amount
        }
    }
}

This allows the application to use the actual block chain code to handle data stored on the blockchain.