Documentation
¶
Overview ¶
Package util provides Ethereum-compatible cryptographic signing utilities. This file contains functions for handling Ethereum-style message signing and signature recovery, implementing EIP-191 and EIP-155 standards for message authentication.
Package util provides utility functions and types for the Hyperlane Morpheum project. This package contains core data structures and helper functions used across the application, including address handling, cryptographic operations, pagination, and routing mechanisms.
Package util provides utility functions for working with Hyperlane protocol messages. Hyperlane is a universal interoperability protocol that enables secure communication between different blockchain networks.
Package util provides utility functions for cryptographic operations and data structures. This file implements an incremental Merkle tree data structure optimized for blockchain applications.
Package util provides pagination utilities for Cosmos SDK collections. This file contains functions for implementing efficient pagination over collections.Map data structures, supporting both simple key-based pagination and prefix-based pagination for complex key structures like Pair[K1, K2].
Package util provides post-dispatch hook metadata structures for Hyperlane message processing. This file defines the metadata structure used by post-dispatch hooks to handle message processing, fee collection, and custom hook logic in the Cosmos ecosystem.
Package util provides a generic router system for managing and routing to different module types. This file implements a flexible routing mechanism that allows dynamic registration and retrieval of modules based on their type identifiers, with support for generating unique addresses and managing module sequences.
Index ¶
- Constants
- Variables
- func BranchRoot(item [32]byte, branch [TreeDepth][32]byte, index uint32) [32]byte
- func DecodeEthHex(s string) ([]byte, error)
- func EncodeEthHex(b []byte) string
- func ExampleRetryStrategy()
- func ExampleRetryStrategyAdvanced()
- func ExampleRetryStrategyExponentialBackoff()
- func ExampleRetryStrategyRealWorld()
- func ExampleRetryStrategySchedule()
- func ExampleRetryStrategyWithCallback()
- func ExampleRetryStrategyWithConditionalRetry()
- func ExampleRetryStrategyWithContext()
- func GetEthSigningHash(msg []byte) [32]byte
- func GetPaginatedFromMap[T any, K any](ctx context.Context, collection collections.Map[K, T], ...) ([]T, *query.PageResponse, error)
- func GetPaginatedPrefixFromMap[T any, K1 any, K2 any](ctx context.Context, collection collections.Map[collections.Pair[K1, K2], T], ...) ([]T, *query.PageResponse, error)
- func PackAny(item proto.Message) (*codectypes.Any, error)
- func PackAnys(isms []proto.Message) ([]*codectypes.Any, error)
- func RecoverEthSignature(hash []byte, sig []byte) (*ecdsa.PublicKey, error)
- func RunAllExamples()
- type HexAddress
- func (h HexAddress) Bytes() []byte
- func (h HexAddress) Compare(other HexAddress) int
- func (h HexAddress) Equal(other HexAddress) bool
- func (h HexAddress) GetInternalId() uint64
- func (h HexAddress) GetType() uint32
- func (h HexAddress) IsZeroAddress() bool
- func (h HexAddress) Marshal() ([]byte, error)
- func (h HexAddress) MarshalJSON() ([]byte, error)
- func (h *HexAddress) MarshalTo(data []byte) (n int, err error)
- func (h *HexAddress) Size() int
- func (h HexAddress) String() string
- func (h *HexAddress) Unmarshal(data []byte) error
- func (h *HexAddress) UnmarshalJSON(data []byte) error
- type HyperlaneApp
- type HyperlaneMessage
- type InterchainSecurityModule
- type MerkleTree
- type PostDispatchModule
- type Ranger
- type RetryConfig
- type RetryInfo
- type RetryStrategy
- func (rs *RetryStrategy) Execute(fn func() error) error
- func (rs *RetryStrategy) GetDelayForAttempt(attempt int) time.Duration
- func (rs *RetryStrategy) GetRetrySchedule(maxAttempts int) []RetryInfo
- func (rs *RetryStrategy) String() string
- func (rs *RetryStrategy) WithContext(ctx context.Context) *RetryStrategy
- func (rs *RetryStrategy) WithMaxRetries(maxRetries int) *RetryStrategy
- func (rs *RetryStrategy) WithOnRetry(callback func(attempt int, err error, delay time.Duration)) *RetryStrategy
- func (rs *RetryStrategy) WithShouldRetry(shouldRetry func(error) bool) *RetryStrategy
- type Router
- func (r *Router[T]) GetInternalSequence(ctx context.Context) (uint64, error)
- func (r *Router[T]) GetModule(id HexAddress) (*T, error)
- func (r *Router[T]) GetModuleIds() (moduleIds []uint32)
- func (r *Router[T]) GetNextSequence(ctx context.Context, moduleId uint8) (HexAddress, error)
- func (r *Router[T]) RegisterModule(moduleId uint8, module T)
- func (r *Router[T]) SetInternalSequence(ctx context.Context, value uint64) error
- type StandardHookMetadata
Constants ¶
const ( // HEX_ADDRESS_LENGTH defines the total byte length of a HexAddress (32 bytes) HEX_ADDRESS_LENGTH = 32 // ENCODED_HEX_ADDRESS_LENGTH defines the length of the hex-encoded string representation // (0x prefix + 32 bytes hex encoded = 66 bytes total) ENCODED_HEX_ADDRESS_LENGTH = 66 )
SPEC: HexAddress
The HexAddress mimics an evm-compatible address for a smart contract. Due to the nature of cosmos, addresses must be created differently.
Requirements: - HexAddresses must be unique across all cosmos modules interacting with Hyperlane
Structure - The HexAddress has 32 bytes and is used for external communication - For internal usage and storage an uint64 is totally sufficient
Encoding: - 0:20 bytes are the module identifier - 20:24 bytes is the module type. This is used to identify the correct module implementation for this type in the router. See `util./router.go` - 24:32 bytes is the internal id. Can be used for internal collection storage.
Constants defining the structure and layout of HexAddress
const ( // VersionOffset is the byte position where the message version is stored (1 byte) VersionOffset = 0 // NonceOffset is the byte position where the nonce starts (4 bytes, big-endian) NonceOffset = 1 // OriginOffset is the byte position where the origin domain ID starts (4 bytes, big-endian) OriginOffset = 5 // SenderOffset is the byte position where the sender address starts (32 bytes) SenderOffset = 9 // DestinationOffset is the byte position where the destination domain ID starts (4 bytes, big-endian) DestinationOffset = 41 // RecipientOffset is the byte position where the recipient address starts (32 bytes) RecipientOffset = 45 // BodyOffset is the byte position where the message body/payload starts (variable length) BodyOffset = 77 )
Byte offset constants for parsing Hyperlane message structure. These offsets define the position of each field within the serialized message bytes. The message format follows a fixed-width layout for efficient parsing and validation.
const ( // TreeDepth defines the maximum depth of the Merkle tree (32 levels) // This allows for up to 2^32 - 1 leaves in the tree TreeDepth = 32 // MaxLeaves is the maximum number of leaves that can be inserted into the tree // Calculated as (2^TreeDepth) - 1 = (2^32) - 1 = 4,294,967,295 MaxLeaves = (1 << TreeDepth) - 1 )
Constants defining the Merkle tree configuration
const ( // MAX_QUERY_LIMIT defines the maximum number of items that can be returned in a single paginated query. // This prevents excessive memory usage and ensures reasonable response times. MAX_QUERY_LIMIT = 1000 )
Constants for pagination configuration
Variables ¶
var ZeroHashes = [TreeDepth][32]byte{
hexToBytes("0000000000000000000000000000000000000000000000000000000000000000"),
hexToBytes("ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"),
hexToBytes("b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30"),
hexToBytes("21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85"),
hexToBytes("e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344"),
hexToBytes("0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d"),
hexToBytes("887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968"),
hexToBytes("ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83"),
hexToBytes("9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af"),
hexToBytes("cefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0"),
hexToBytes("f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5"),
hexToBytes("f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892"),
hexToBytes("3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c"),
hexToBytes("c1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb"),
hexToBytes("5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc"),
hexToBytes("da7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2"),
hexToBytes("2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f"),
hexToBytes("e1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a"),
hexToBytes("5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0"),
hexToBytes("b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0"),
hexToBytes("c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2"),
hexToBytes("f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9"),
hexToBytes("5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377"),
hexToBytes("4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652"),
hexToBytes("cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef"),
hexToBytes("0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d"),
hexToBytes("b8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0"),
hexToBytes("838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e"),
hexToBytes("662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e"),
hexToBytes("388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322"),
hexToBytes("93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735"),
hexToBytes("8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"),
}
ZeroHashes represents a precomputed array of zero hashes for each level of the tree. These are the default hash values used when a branch doesn't exist at a particular level. This optimization allows for efficient root calculation without storing the entire tree.
The zero hashes are computed as: - Level 0: 32 zero bytes (0x0000...0000) - Level i: Keccak256(ZeroHashes[i-1], ZeroHashes[i-1]) for i > 0
These values are used in root calculation when a branch is missing at a given level.
Functions ¶
func BranchRoot ¶
BranchRoot calculates and returns the Merkle root for a given leaf, branch, and index. This function is used for Merkle proof verification - it reconstructs the root hash from a leaf and its corresponding branch (proof path) to verify inclusion.
The algorithm works by: 1. Starting with the leaf hash 2. For each level, combining the current hash with the corresponding branch hash 3. The order of combination depends on the bit position in the index
Parameters:
- item: The leaf hash to verify
- branch: The Merkle proof path (branch hashes from leaf to root)
- index: The position of the leaf in the tree (0-based)
Returns:
- [32]byte: The computed root hash that should match the tree's root
Algorithm:
The function uses the binary representation of the index to determine the order of hash combination at each level. If the i-th bit is 1, the branch hash is the left child; if 0, it's the right child.
func DecodeEthHex ¶
DecodeEthHex decodes a hex-encoded string to raw bytes, handling Ethereum-style hex format.
This function removes the optional "0x" prefix and decodes the remaining hex string to bytes. It's commonly used for processing Ethereum addresses, transaction hashes, and other hex-encoded data.
Parameters:
- s: The hex-encoded string, optionally prefixed with "0x"
Returns:
- []byte: The decoded raw bytes
- error: Any error encountered during decoding
func EncodeEthHex ¶
EncodeEthHex encodes raw bytes to a hex string with Ethereum-style "0x" prefix.
This function converts raw bytes to a hex-encoded string and adds the "0x" prefix, which is the standard format used throughout the Ethereum ecosystem. It's commonly used for formatting addresses, hashes, and other binary data.
Parameters:
- b: The raw bytes to encode
Returns:
- string: The hex-encoded string with "0x" prefix
func ExampleRetryStrategy ¶
func ExampleRetryStrategy()
ExampleRetryStrategy demonstrates various ways to use the retry strategy
func ExampleRetryStrategyAdvanced ¶
func ExampleRetryStrategyAdvanced()
ExampleRetryStrategyAdvanced demonstrates advanced usage patterns
func ExampleRetryStrategyExponentialBackoff ¶
func ExampleRetryStrategyExponentialBackoff()
ExampleRetryStrategyExponentialBackoff demonstrates the exponential backoff for high retry counts
func ExampleRetryStrategyRealWorld ¶
func ExampleRetryStrategyRealWorld()
ExampleRetryStrategyRealWorld demonstrates a real-world usage scenario
func ExampleRetryStrategySchedule ¶
func ExampleRetryStrategySchedule()
ExampleRetryStrategySchedule demonstrates viewing the retry schedule
func ExampleRetryStrategyWithCallback ¶
func ExampleRetryStrategyWithCallback()
ExampleRetryStrategyWithCallback demonstrates using retry callbacks
func ExampleRetryStrategyWithConditionalRetry ¶
func ExampleRetryStrategyWithConditionalRetry()
ExampleRetryStrategyWithConditionalRetry demonstrates conditional retry logic
func ExampleRetryStrategyWithContext ¶
func ExampleRetryStrategyWithContext()
ExampleRetryStrategyWithContext demonstrates context cancellation
func GetEthSigningHash ¶
GetEthSigningHash hashes a message according to EIP-191 standard.
This function implements the Ethereum Signed Message format, which provides a standardized way to sign arbitrary data. The message is enveloped with a specific prefix to prevent signature reuse across different contexts.
The enveloping format follows EIP-191: `"\x19Ethereum Signed Message:\n" + message.length + message`
Parameters:
- msg: The raw message bytes to be signed
Returns:
- [32]byte: The Keccak256 hash of the enveloped message
func GetPaginatedFromMap ¶
func GetPaginatedFromMap[T any, K any](ctx context.Context, collection collections.Map[K, T], pagination *query.PageRequest) ([]T, *query.PageResponse, error)
GetPaginatedFromMap retrieves paginated entries from a collections.Map where keys are of type K and values are of type T. Returns them according to pagination parameters.
This function provides a simpler pagination interface for collections with single-type keys. It's the basic pagination function that GetPaginatedPrefixFromMap builds upon for more complex composite key scenarios.
Parameters:
- ctx: Context for the operation, used for cancellation and timeouts
- collection: The collections.Map containing the data, with K keys and T values
- pagination: Query pagination parameters including limit, key, and reverse ordering
Returns:
- []T: Slice of paginated values
- *query.PageResponse: Pagination metadata including the next key if more results exist
- error: Any error encountered during the operation
Pagination behavior:
- If no pagination is provided, defaults to counting total with default limit
- Key-based pagination can be used, offset is not supported for performance reasons
- For key-based pagination, uses provided key as start/end boundary
- In reverse order, results are returned in descending order
- Returns nextKey in PageResponse if more results exist beyond the current page
Note: This is a simpler version of GetPaginatedPrefixFromMap that works with any key type K
func GetPaginatedPrefixFromMap ¶
func GetPaginatedPrefixFromMap[T any, K1 any, K2 any](ctx context.Context, collection collections.Map[collections.Pair[K1, K2], T], pagination *query.PageRequest, prefix K1) ([]T, *query.PageResponse, error)
GetPaginatedPrefixFromMap retrieves paginated entries from a collections.Map where keys are pairs [K1, K2] and values are of type T. It filters entries by a prefix of type K1 and returns them according to pagination parameters.
This function is designed for collections that use composite keys where you want to filter by the first component of the key pair. It's particularly useful for relational data where you need to query all entries associated with a specific prefix.
Parameters:
- ctx: Context for the operation, used for cancellation and timeouts
- collection: The collections.Map containing the data, with Pair[K1, K2] keys and T values
- pagination: Query pagination parameters including limit, key, and reverse ordering
- prefix: The K1 type prefix to filter entries by
Returns:
- []T: Slice of paginated values matching the prefix
- *query.PageResponse: Pagination metadata including the next key if more results exist
- error: Any error encountered during the operation
Pagination behavior:
- If no pagination is provided, defaults to counting total with default limit
- Key-based pagination can be used, offset is not supported for performance reasons
- For key-based pagination, decodes the provided key and uses it as start/end boundary
- In reverse order, results are returned in descending order
- Returns nextKey in PageResponse if more results exist beyond the current page
Note: This implementation assumes the collection's KeyCodec can properly handle Pair[K1, K2] keys
func RecoverEthSignature ¶
RecoverEthSignature recovers the public key from a given signature and message hash.
This function implements EIP-155 signature recovery, which allows extracting the public key that was used to sign a message from the signature itself. The signature must follow the standard 65-byte format with recovery ID.
Signature format:
- First 32 bytes: R component of the signature
- Next 32 bytes: S component of the signature
- Last byte: Recovery ID (27 or 28 for EIP-155)
Parameters:
- hash: The 32-byte message hash that was signed
- sig: The 65-byte signature (R + S + recovery_id)
Returns:
- *ecdsa.PublicKey: The recovered public key, or nil if recovery fails
- error: Any error encountered during recovery
Types ¶
type HexAddress ¶
type HexAddress [HEX_ADDRESS_LENGTH]byte
HexAddress represents a 32-byte address structure that mimics EVM-compatible addresses for smart contracts in the Cosmos ecosystem. It provides a standardized way to represent module addresses with embedded type and ID information.
func CreateMockHexAddress ¶
func CreateMockHexAddress(identifier string, id int64) HexAddress
CreateMockHexAddress generates a deterministic HexAddress for testing purposes. It creates a SHA256 hash from the concatenation of the identifier string and the ID. This function is primarily used in testing scenarios where deterministic addresses are needed.
func DecodeHexAddress ¶
func DecodeHexAddress(s string) (HexAddress, error)
DecodeHexAddress parses a hex-encoded string and converts it to a HexAddress. The input string can optionally include the "0x" prefix, which will be stripped. Returns an error if the string length is invalid or contains non-hex characters.
func GenerateHexAddress ¶
func GenerateHexAddress(moduleSpecifier [module_length]byte, internalType uint32, internalId uint64) HexAddress
GenerateHexAddress creates a new HexAddress with the specified components. This is the primary constructor for creating properly structured HexAddresses with module specifier, type, and internal ID components.
Parameters:
- moduleSpecifier: 20-byte module identifier
- internalType: 4-byte module type identifier
- internalId: 8-byte internal ID for collection storage
func NewZeroAddress ¶
func NewZeroAddress() HexAddress
NewZeroAddress creates and returns a new HexAddress initialized with all zero bytes. This represents an uninitialized or null address state.
func (HexAddress) Bytes ¶
func (h HexAddress) Bytes() []byte
Bytes returns the raw byte slice representation of the HexAddress. This is useful for internal operations that need direct byte access.
func (HexAddress) Compare ¶
func (h HexAddress) Compare(other HexAddress) int
Compare compares two HexAddresses lexicographically. Returns -1 if h < other, 0 if h == other, or 1 if h > other. This method is useful for sorting and ordering operations.
func (HexAddress) Equal ¶
func (h HexAddress) Equal(other HexAddress) bool
Equal checks if two HexAddresses are equal by comparing their byte representations. Returns true if both addresses have identical byte content.
func (HexAddress) GetInternalId ¶
func (h HexAddress) GetInternalId() uint64
GetInternalId extracts the internal ID from the HexAddress. The internal ID is stored in bytes 24-31 and represents a unique identifier for internal collection storage and management.
func (HexAddress) GetType ¶
func (h HexAddress) GetType() uint32
GetType extracts the module type from the HexAddress. The module type is stored in bytes 20-23 and is used to identify the correct module implementation in the router system.
func (HexAddress) IsZeroAddress ¶
func (h HexAddress) IsZeroAddress() bool
IsZeroAddress checks if the HexAddress is the zero address (all bytes are 0). Returns true if the address is uninitialized or represents a null address.
func (HexAddress) Marshal ¶
func (h HexAddress) Marshal() ([]byte, error)
Marshal implements the protobuf Marshaler interface. Returns the hex-encoded string representation as bytes.
func (HexAddress) MarshalJSON ¶
func (h HexAddress) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface. Returns the hex-encoded string representation as JSON.
func (*HexAddress) MarshalTo ¶
func (h *HexAddress) MarshalTo(data []byte) (n int, err error)
MarshalTo implements the protobuf MarshalerTo interface. Writes the hex-encoded string representation to the provided byte slice. Returns the number of bytes written and an error if the buffer is too small.
func (*HexAddress) Size ¶
func (h *HexAddress) Size() int
Size implements the protobuf Sizer interface. Returns the fixed size of the hex-encoded string representation.
func (HexAddress) String ¶
func (h HexAddress) String() string
String returns the hex-encoded string representation of the HexAddress with "0x" prefix. This format is compatible with EVM address representations and is used for external communication.
func (*HexAddress) Unmarshal ¶
func (h *HexAddress) Unmarshal(data []byte) error
Unmarshal implements the protobuf Unmarshaler interface. Parses the hex-encoded string representation from the provided byte slice. Returns an error if the data length is invalid or contains invalid hex characters.
func (*HexAddress) UnmarshalJSON ¶
func (h *HexAddress) UnmarshalJSON(data []byte) error
UnmarshalJSON implements the json.Unmarshaler interface. Parses the hex-encoded string representation from JSON data. Returns an error if the JSON data is invalid or contains invalid hex characters.
type HyperlaneApp ¶
type HyperlaneApp interface {
// Exists checks if an application with the given recipient address exists.
Exists(ctx context.Context, recipient HexAddress) (bool, error)
// Handle processes a received Hyperlane message.
// This is where the actual application logic is executed.
Handle(ctx context.Context, mailboxId HexAddress, message HyperlaneMessage) error
// ReceiverIsmId returns the ISM ID that should be used for verifying messages
// sent to the specified recipient address.
ReceiverIsmId(ctx context.Context, recipient HexAddress) (*HexAddress, error)
}
HyperlaneApp defines the interface for Hyperlane application modules. These modules handle the actual processing of messages and implement the business logic for cross-chain communication.
type HyperlaneMessage ¶
type HyperlaneMessage struct {
// Version specifies the protocol version for message format compatibility
Version uint8
// Nonce is a unique identifier for message ordering and replay protection
Nonce uint32
// Origin is the domain ID of the blockchain where this message originated
Origin uint32
// Sender is the address of the account that initiated this cross-chain message
Sender HexAddress
// Destination is the domain ID of the target blockchain for this message
Destination uint32
// Recipient is the address on the destination chain that will receive this message
Recipient HexAddress
// Body contains the actual message payload/data to be delivered
Body []byte
}
HyperlaneMessage implements the Hyperlane message specification for cross-chain communication. This struct represents a standardized message format that enables secure and verifiable communication between different blockchain domains in the Hyperlane network.
The message structure follows the official Hyperlane specification: https://docs.hyperlane.xyz/docs/reference/libraries/message
Message Layout (in bytes): [0:1] Version - Protocol version (1 byte) [1:5] Nonce - Message nonce for ordering (4 bytes, big-endian) [5:9] Origin - Source domain ID (4 bytes, big-endian) [9:41] Sender - Source address (32 bytes) [41:45] Destination - Target domain ID (4 bytes, big-endian) [45:77] Recipient - Target address (32 bytes) [77:] Body - Message payload (variable length)
func ParseHyperlaneMessage ¶
func ParseHyperlaneMessage(raw []byte) (HyperlaneMessage, error)
ParseHyperlaneMessage deserializes a raw byte slice into a HyperlaneMessage struct. This function parses the binary message format according to the Hyperlane specification, extracting each field from its designated byte offset and converting multi-byte fields from big-endian format.
Parameters:
- raw: The raw byte slice containing the serialized Hyperlane message
Returns:
- HyperlaneMessage: The parsed message struct
- error: Returns an error if the message is too short or malformed
The function validates that the input has at least the minimum required length (BodyOffset = 77 bytes) before attempting to parse the fixed-width fields.
func (HyperlaneMessage) Bytes ¶
func (msg HyperlaneMessage) Bytes() []byte
Bytes serializes the HyperlaneMessage struct into its binary representation. This method converts the message fields back into the standardized byte format that matches the Hyperlane specification, with proper big-endian encoding for multi-byte integer fields.
The serialization process: 1. Converts uint32 fields (Nonce, Origin, Destination) to 4-byte big-endian format 2. Converts HexAddress fields (Sender, Recipient) to their 32-byte representation 3. Concatenates all fields in the correct order according to the message layout
Returns:
- []byte: The complete serialized message as a byte slice
func (HyperlaneMessage) Id ¶
func (msg HyperlaneMessage) Id() HexAddress
Id computes and returns the unique identifier for this Hyperlane message. The message ID is generated by taking the Keccak256 hash of the serialized message bytes, which provides a deterministic and collision-resistant identifier according to the Hyperlane specification.
This ID is used throughout the Hyperlane protocol for: - Message tracking and indexing - Merkle tree construction for batch verification - Cross-chain message routing and delivery confirmation - Dispute resolution and fraud proofs
Returns:
- HexAddress: The 32-byte Keccak256 hash of the message as a HexAddress
func (HyperlaneMessage) String ¶
func (msg HyperlaneMessage) String() string
String returns a human-readable hex representation of the serialized Hyperlane message. This method provides a convenient way to display the complete message in hexadecimal format with the standard "0x" prefix, making it suitable for logging, debugging, and API responses.
The output format is a single hex string containing all message fields serialized according to the Hyperlane specification, which can be used for: - Message verification and comparison - Cross-chain message transmission - Debugging and troubleshooting - API documentation and examples
Returns:
- string: The hex-encoded message bytes with "0x" prefix
type InterchainSecurityModule ¶
type InterchainSecurityModule interface {
// Exists checks if an ISM with the given ID exists in the system.
Exists(ctx context.Context, ismId HexAddress) (bool, error)
// Verify validates a message against the ISM's security requirements.
// Returns true if the message is valid according to the ISM's verification logic.
Verify(ctx context.Context, ismId HexAddress, metadata []byte, message HyperlaneMessage) (bool, error)
}
InterchainSecurityModule defines the interface for interchain security modules. These modules are responsible for verifying the authenticity and validity of messages received from other chains in the Hyperlane network.
type MerkleTree ¶
type MerkleTree struct {
// Branch stores the current branch hashes at each level of the tree
// Each element represents a hash at depth i in the tree
Branch [TreeDepth][32]byte
// Count tracks the number of leaves currently in the tree
// This is used to determine the tree structure and calculate the root
Count uint32
}
MerkleTree represents an incremental Merkle tree optimized for blockchain applications. This implementation uses a sparse tree approach where only the necessary branch nodes are stored, making it memory-efficient for large trees.
The tree maintains: - Branch: An array of 32-byte hashes representing the current branch from root to leaves - Count: The total number of leaves that have been inserted into the tree
func NewTree ¶
func NewTree(branch [32][32]byte, count uint32) *MerkleTree
NewTree creates a new MerkleTree instance with the given branch and count. This constructor is typically used when reconstructing a tree from stored state.
Parameters:
- branch: A 32-element array of 32-byte hashes representing the current branch
- count: The number of leaves currently in the tree
Returns:
- *MerkleTree: A new MerkleTree instance with the specified branch and count
func (*MerkleTree) GetCount ¶
func (tree *MerkleTree) GetCount() uint32
GetCount returns the current number of leaves in the Merkle tree.
Returns:
- uint32: The number of leaves currently inserted into the tree
func (*MerkleTree) GetLatestCheckpoint ¶
func (tree *MerkleTree) GetLatestCheckpoint() ([32]byte, uint32, error)
GetLatestCheckpoint returns the root hash and index of the most recently inserted leaf. This is useful for creating checkpoints that can be used to verify tree state.
Returns:
- [32]byte: The root hash at the time of the latest leaf insertion
- uint32: The index of the latest leaf (count - 1)
- error: An error if no leaves have been inserted yet
func (*MerkleTree) GetRoot ¶
func (tree *MerkleTree) GetRoot() [32]byte
GetRoot calculates and returns the current root hash of the Merkle tree. The root represents the top-level hash that summarizes the entire tree state.
Returns:
- [32]byte: The 32-byte root hash of the current tree state
func (*MerkleTree) Insert ¶
func (tree *MerkleTree) Insert(node [32]byte) error
Insert adds a new leaf node to the Merkle tree and updates the branch accordingly. This implements an incremental insertion algorithm that efficiently maintains the tree structure without storing the entire tree.
The algorithm works by: 1. Finding the position of the new leaf based on the current count 2. Walking up the tree, combining hashes as needed 3. Updating the branch array to reflect the new tree state
Parameters:
- node: A 32-byte hash representing the new leaf to insert
Returns:
- error: An error if the tree is already full (has reached MaxLeaves)
Algorithm:
The insertion uses the binary representation of the count to determine the path through the tree. For each bit position, if the bit is 1, we store the current node at that level and return. If the bit is 0, we combine the current node with the existing branch hash and continue.
type PostDispatchModule ¶
type PostDispatchModule interface {
// Exists checks if a post-dispatch hook with the given ID exists in the system.
Exists(ctx context.Context, hookId HexAddress) (bool, error)
// PostDispatch executes the post-dispatch logic and returns the coins charged.
// This method is called after message dispatch to handle fees and custom processing.
PostDispatch(ctx context.Context, mailboxId, hookId HexAddress, metadata StandardHookMetadata, message HyperlaneMessage, maxFee sdk.Coins) (sdk.Coins, error)
// QuoteDispatch provides a fee quote for the post-dispatch operation without executing it.
// This is used for fee estimation and validation before actual dispatch.
QuoteDispatch(ctx context.Context, mailboxId, hookId HexAddress, metadata StandardHookMetadata, message HyperlaneMessage) (sdk.Coins, error)
// HookType returns the type identifier for this hook module.
HookType() uint8
}
PostDispatchModule defines the interface for post-dispatch hook modules. These modules are executed after a message has been dispatched and are used for fee collection, gas estimation, and custom processing logic.
type Ranger ¶
type Ranger[K any] struct { // contains filtered or unexported fields }
Ranger is a generic type that implements the collections.Ranger interface for pagination. It defines a range of keys to iterate over with a specific ordering.
Type parameters:
- K: The type of keys in the collection
func (Ranger[K]) RangeValues ¶
func (r Ranger[K]) RangeValues() (start, end *collections.RangeKey[K], order collections.Order, err error)
RangeValues implements the collections.Ranger interface. Returns the range boundaries and ordering for iteration.
type RetryConfig ¶
type RetryConfig struct {
// MaxRetries is the maximum number of retry attempts (0 means unlimited)
MaxRetries int
// Context for cancellation
Context context.Context
// OnRetry is called before each retry attempt
OnRetry func(attempt int, err error, delay time.Duration)
// ShouldRetry determines if an error should trigger a retry
ShouldRetry func(error) bool
}
RetryConfig holds configuration for retry behavior
type RetryStrategy ¶
type RetryStrategy struct {
// contains filtered or unexported fields
}
RetryStrategy defines the retry timing strategy
func NewRetryStrategy ¶
func NewRetryStrategy() *RetryStrategy
NewRetryStrategy creates a new retry strategy with the default configuration
func (*RetryStrategy) Execute ¶
func (rs *RetryStrategy) Execute(fn func() error) error
Execute runs a function with retry logic
func (*RetryStrategy) GetDelayForAttempt ¶
func (rs *RetryStrategy) GetDelayForAttempt(attempt int) time.Duration
GetDelayForAttempt returns the delay for a specific attempt number without executing retry logic
func (*RetryStrategy) GetRetrySchedule ¶
func (rs *RetryStrategy) GetRetrySchedule(maxAttempts int) []RetryInfo
GetRetrySchedule returns a slice of RetryInfo for the first N attempts
func (*RetryStrategy) String ¶
func (rs *RetryStrategy) String() string
String returns a human-readable description of the retry strategy
func (*RetryStrategy) WithContext ¶
func (rs *RetryStrategy) WithContext(ctx context.Context) *RetryStrategy
WithContext sets the context for cancellation
func (*RetryStrategy) WithMaxRetries ¶
func (rs *RetryStrategy) WithMaxRetries(maxRetries int) *RetryStrategy
WithMaxRetries sets the maximum number of retries
func (*RetryStrategy) WithOnRetry ¶
func (rs *RetryStrategy) WithOnRetry(callback func(attempt int, err error, delay time.Duration)) *RetryStrategy
WithOnRetry sets the callback function called before each retry
func (*RetryStrategy) WithShouldRetry ¶
func (rs *RetryStrategy) WithShouldRetry(shouldRetry func(error) bool) *RetryStrategy
WithShouldRetry sets the function that determines if an error should trigger a retry
type Router ¶
type Router[T any] struct { // contains filtered or unexported fields }
Router is a generic router that manages modules of type T and provides functionality for module registration, retrieval, and address generation. It uses a sequence counter to generate unique addresses for new modules.
Type parameters:
- T: The type of modules managed by this router (must implement one of the module interfaces)
func NewRouter ¶
func NewRouter[T any](keyPrefix []byte, name string, builder *collections.SchemaBuilder) *Router[T]
NewRouter creates a new router instance with the specified configuration. The router name is used as a prefix for generating unique module addresses.
Parameters:
- keyPrefix: The key prefix for the sequence storage
- name: The router name (must be at most 20 bytes)
- builder: The collections schema builder for sequence initialization
Returns:
- *Router[T]: A new router instance
Panics:
- If the router name exceeds the maximum length of 20 bytes
func (*Router[T]) GetInternalSequence ¶
GetInternalSequence returns the current value of the internal sequence counter without incrementing it. This is useful for checking the current state.
Parameters:
- ctx: Context for the operation
Returns:
- uint64: The current sequence value
- error: Any error encountered during the operation
func (*Router[T]) GetModule ¶
func (r *Router[T]) GetModule(id HexAddress) (*T, error)
GetModule retrieves a module instance based on the module type embedded in the HexAddress. The module type is extracted from bytes 20-23 of the address using the GetType() method.
Parameters:
- id: The HexAddress containing the module type information
Returns:
- *T: A pointer to the module instance, or nil if not found
- error: An error if the module type is not registered
func (*Router[T]) GetModuleIds ¶
GetModuleIds returns a sorted list of all registered module IDs. This is useful for enumeration and debugging purposes.
Returns:
- []uint32: A sorted slice of all registered module IDs
func (*Router[T]) GetNextSequence ¶
GetNextSequence generates the next unique address for a module of the specified type. This method increments the internal sequence counter and creates a new HexAddress that combines the router name, module type, and sequence number.
Parameters:
- ctx: Context for the operation
- moduleId: The module type ID for which to generate an address
Returns:
- HexAddress: A new unique address for the module
- error: An error if the sequence cannot be incremented or the module type is not registered
func (*Router[T]) RegisterModule ¶
RegisterModule registers a new module with the specified ID in the router. Each module ID can only be registered once to prevent conflicts.
Parameters:
- moduleId: The unique identifier for the module type (uint8)
- module: The module instance to register
Panics:
- If a module with the same ID has already been registered
func (*Router[T]) SetInternalSequence ¶
SetInternalSequence sets the internal sequence counter to a specific value. This is primarily used for initialization and testing purposes.
Parameters:
- ctx: Context for the operation
- value: The new sequence value to set
Returns:
- error: Any error encountered during the operation
type StandardHookMetadata ¶
type StandardHookMetadata struct {
// Address represents the Cosmos account address of the message sender.
// This is used to determine the origin of the message and is particularly
// important for fee collection mechanisms like Interchain Gas Payment (IGP).
// The address is used to identify which account should be charged for
// the message processing and gas costs.
Address sdk.AccAddress
// GasLimit specifies the maximum amount of gas that can be consumed
// by the destination transaction. This is used for gas estimation and
// fee calculation purposes. The hook can use this value to determine
// appropriate fees and validate that sufficient gas is allocated.
GasLimit math.Int
// CustomHookMetadata contains application-specific data that can be passed
// to a PostDispatch hook for custom processing logic. The hook implementation
// is responsible for validating, decoding, and processing this custom metadata.
// This field allows for extensibility and custom behavior in hook implementations.
CustomHookMetadata []byte
}
StandardHookMetadata contains the metadata required for post-dispatch hook processing. This structure is application-specific and differs from the EVM implementation to accommodate Cosmos SDK patterns and requirements.
Post-dispatch hooks are executed after a message has been dispatched and are used for various purposes such as fee collection, gas estimation, and custom processing logic.