Skip to main content

Encoding

Data conversion from one format to another to increase security and efficiency is referred to as encoding. Encoding is used in the context of blockchain to make sure that data is saved and sent in a fashion that is safe and simple to use.

The execution clients for Ethereum frequently use the serialization format known as Recursive Length Prefix (RLP). It is the primary encoding technique used to serialize objects in Ethereum, and its function is to encode arbitrarily nested arrays of binary data. RLP simply encodes structure; higher-order protocols are responsible for encoding particular atomic data types like strings, integers, and floats.

In Ethereum, integers are represented in big-endian binary form without leading zeroes, which means that the integer value zero is equivalent to an empty byte array. The RLP encoding function takes an item as input, which can be a single byte with a value between 0x00 and 0x7f, or a string of up to 55 bytes. If the string is longer than 55 bytes, the RLP encoding consists of a single byte with value 0xb7 (dec. 183) followed by the length of the string in binary form, then the length of the string, and finally the string itself. RLP is used for various purposes such as hash verification, transaction signing, and data encoding. It is also used for efficient encoding of the merkle tree data structure in some cases. The Ethereum execution layer primarily uses RLP for serializing objects, but the newer Simple Serialize (SSZ) is replacing RLP as the encoding method for the new consensus layer in Ethereum 2.0.

The Cosmos Stargate release introduces protobuf as the main encoding format for both client and state serialization. All EVM module types used for state and clients, such as transaction messages, genesis, query services, etc., will be implemented as protocol buffer messages. Additionally, the Cosmos SDK supports the legacy Amino encoding. Protocol Buffers (protobuf) is a binary serialization format that is smaller and faster than JSON. It is designed to efficiently serialize structured data, such as messages, and can be used to generate code for various programming languages. The main advantage of protobuf is its efficiency, resulting in smaller message sizes and faster serialization and deserialization times. The RLP decoding process involves examining the first byte of input data to determine the data type and length, and then decoding the data accordingly.

Prerequisite Readings

Encoding Formats

Protocol Buffers

The protobuf encoding standard is introduced in the Cosmos Stargate release as the primary encoding format for both client and state serialization. All of the EVM module kinds (transaction messages, genesis, query services, etc.) that are utilized for state and clients will be implemented as protocol buffer messages.

Amino

For backwards compatibility with earlier releases, the Cosmos SDK also supports the traditional Amino encoding standard, particularly for client encoding and signing with Ledger devices. Amino is supported by all other Cosmos SDK modules, however Humans.ai does not support it in the EVM module.

RLP

The encoding/decoding algorithm Recursive Length Prefix (RLP) serializes a message and enables speedy decoding of encoded data. In order to handle JSON-RPC and conform messages to the right Ethereum format, Humans.ai employs RLP to encode and decode Ethereum messages. This makes it possible to encrypt and decrypt messages in a manner identical to Ethereum's.

By converting the message to a go-ethereum's Transaction and marshaling the transaction data using RLP, the x/evm transactions (MsgEthereumTx) are encoded:

// TxEncoder overwrites sdk.TxEncoder to support MsgEthereumTx
func (g txConfig) TxEncoder() sdk.TxEncoder {
return func(tx sdk.Tx) ([]byte, error) {
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if ok {
return msg.AsTransaction().MarshalBinary()
}
return g.TxConfig.TxEncoder()(tx)
}
}

// TxDecoder overwrites sdk.TxDecoder to support MsgEthereumTx
func (g txConfig) TxDecoder() sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, error) {
tx := &ethtypes.Transaction{}

err := tx.UnmarshalBinary(txBytes)
if err == nil {
msg := &evmtypes.MsgEthereumTx{}
msg.FromEthereumTx(tx)
return msg, nil
}

return g.TxConfig.TxDecoder()(txBytes)
}
}