How Starship Enables Inter-Blockchain Communication (IBC) Support
Starship enables Inter-Blockchain Communication (IBC) support by querying on-chain state from Cosmos-SDK chains, aggregating channel and connection data into protobuf models, and exposing discovery endpoints via gRPC and REST.
The hyperweb-io/starship registry service acts as a central discovery hub for IBC topology. It inspects live chain states to build a unified view of cross-chain connections, making IBC path discovery programmatically accessible for developers and external services.
Architecture of Starship IBC Discovery
Starship’s IBC support relies on a configuration-driven relayer setup paired with active on-chain querying to construct a real-time registry of inter-blockchain connections.
Configuration-Driven Relayer Setup
The registry reads the relayers section of the Starship configuration to identify active IBC paths. Each relayer (such as Hermes or ts-relayer) creates the necessary IBC client, connection, and channel objects on the source chains. The registry service uses this configuration to determine which chain pairs to monitor, then queries their on-chain states directly to verify and aggregate connection metadata.
On-Chain Data Aggregation with ChainClient
For every configured chain, the ChainClient.GetChainInfo method in starship/registry/chain.go (lines 10-55) performs three critical queries:
- Channel ports via
Ibc_Channelquery to enumerate active channels. - Connection details via
Ibc_Connectionquery (seegetConnectionClient) to fetch connection identifiers. - Counter-party chain ID via
Ibc_ClientStatequery to unpack the Tendermint client state and resolve the remote chain identifier (getChainIdFromClient).
The method aggregates these results into a slice of ChainIBCInfo structs containing local and counter-party IBCInfo, along with channel ordering, version, and state data. The ChainIBCInfos collection is then converted to protobuf format via ToProto() for transport.
// starship/registry/chain.go
func (c *ChainClient) GetChainInfo() (ChainIBCInfos, error) {
// …query channels, connections, client state…
// build ChainIBCInfo structs
}
Core Registry Endpoints for IBC Queries
The registry handler exposes three RPC methods that allow users to discover IBC connections at different granularity levels.
ListIBC and ListChainIBC Handlers
Implemented in starship/registry/handler.go (lines 51-63), the ListIBC endpoint iterates over all configured chainClients, invokes GetChainInfo for each, and concatenates the protobuf results into a comprehensive list.
// starship/registry/handler.go
func (a *AppServer) ListIBC(ctx context.Context, _ *emptypb.Empty) (*pb.ResponseListIBC, error) {
var resData []*pb.IBCData
for _, client := range a.chainClients {
infos, err := client.GetChainInfo()
if err != nil { return nil, err }
resData = append(resData, infos.ToProto()...)
}
return &pb.ResponseListIBC{Data: resData}, nil
}
ListChainIBC filters this aggregation to return only connections where the specified chain participates, enabling targeted queries for specific network topologies.
GetIBCInfo for Specific Chain Pairs
The GetIBCInfo handler accepts a pair of chain IDs, loads the source chain’s ChainClient, retrieves its full IBC list, and scans for the matching counter-party entry. When found, it returns a single IBCData record containing the channel ID, connection ID, client ID, and state; otherwise, it returns an error indicating no path exists between the requested chains.
Protocol Buffer Definitions and Generated Code
The data models and service definitions reside in the starship/proto/registry/ directory.
ibc.proto defines the core structures:
IBCChain: Chain identifiers and metadata.ChannelData: Channel ID, port ID, ordering, and state.IBCData: Complete connection record linking two chains via channels and connections.
service.proto declares the RPC methods:
ListIBC:GET /ibc– Returns all IBC connections.ListChainIBC:GET /ibc/{chain}– Returns connections for a specific chain.GetIBCInfo:GET /ibc/{chain_1}/{chain_2}– Returns details for a specific pair.
The build process generates:
starship/registry/registry/service_grpc.pb.go: gRPC client and server interfaces.starship/registry/registry/service.pb.gw.go: REST-gateway HTTP handlers that map the above routes to the Go methods.
Practical Usage Examples
Querying All IBC Connections via gRPC
Use the generated client stub from service_grpc.pb.go (lines 139-144) to fetch the complete IBC topology:
import (
"context"
"log"
pb "github.com/hyperweb-io/starship/registry/registry"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("localhost:9090", grpc.WithInsecure())
if err != nil { log.Fatalf("dial: %v", err) }
defer conn.Close()
client := pb.NewRegistryClient(conn)
resp, err := client.ListIBC(context.Background(), &pb.Empty{})
if err != nil { log.Fatalf("ListIBC: %v", err) }
for _, ibc := range resp.Data {
log.Printf("%s ↔ %s (channel %s)", ibc.Chain_1.ChainName, ibc.Chain_2.ChainName, ibc.Channels[0].ChannelId)
}
}
HTTP Requests for Chain-Specific Data
Retrieve IBC connections for a single chain using the REST gateway mapped in service.pb.gw.go:
curl http://localhost:8080/ibc/osmosis-1
Fetch detailed connection information between two specific chains:
curl http://localhost:8080/ibc/osmosis-1/juno-2
The second request returns a JSON object containing the IBCData structure, including channel IDs, connection IDs, and client states for the Osmosis-Juno path.
Summary
- Starship IBC support centers on the registry service, which queries live chain states to discover active channels and connections.
- The
ChainClient.GetChainInfomethod inchain.goaggregates channel, connection, and client-state data intoChainIBCInfostructs. - Three gRPC/HTTP endpoints—
ListIBC,ListChainIBC, andGetIBCInfo—expose this data via the handlers defined inhandler.go. - Protocol buffer definitions in
ibc.protoandservice.protogenerate type-safe Go code and REST-gateway bindings for cross-language compatibility. - Configuration-driven relayer definitions inform the registry which chain pairs to monitor, ensuring the discovery service reflects the actual IBC topology defined in the Starship environment.
Frequently Asked Questions
How does Starship discover IBC connections between chains?
Starship discovers IBC connections by querying the on-chain state of each configured chain through the ChainClient. It inspects the IBC module’s channel, connection, and client state stores to build a complete map of active paths, then aggregates this data into the registry service.
What endpoints are available for querying IBC data?
The registry exposes three primary endpoints: ListIBC returns all connections across every monitored chain; ListChainIBC filters results to a specific chain; and GetIBCInfo retrieves detailed connection metadata for a specific pair of chain IDs. These are available via both gRPC and REST.
Which source files handle the IBC discovery logic?
The discovery logic is split between starship/registry/chain.go, which contains the GetChainInfo method for on-chain queries, and starship/registry/handler.go, which implements the ListIBC, ListChainIBC, and GetIBCInfo RPC handlers. Protocol definitions live in starship/proto/registry/ibc.proto and service.proto.
How does the registry know which chains to monitor for IBC paths?
The registry reads the relayers section of the Starship configuration file to identify which chains have active relayers (such as Hermes or ts-relayer) linking them. This configuration determines the set of chain clients instantiated to query for IBC state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →