Skip to content

feat: IBC v2 support#18

Open
clockworkgr wants to merge 22 commits intomainfrom
feat/ibcv2
Open

feat: IBC v2 support#18
clockworkgr wants to merge 22 commits intomainfrom
feat/ibcv2

Conversation

@clockworkgr
Copy link
Member

@clockworkgr clockworkgr commented Feb 5, 2026

eThis PR adds an implementation of VaaS using IBC v2.

IBC v1 interfaces have been deprecated rather than removed.

The following assumptions were made:

  • Only v2 genesis supported
  • HandshakeMetadata from channel hhandshake not applicable/removed
  • Out-of-order delivery of VSC updates is acceptable; consumer applies latest valset_update_id
  • No explicit sequence number. Consumer tracks highest processed valset_update_id
  • template_client deprecated in favour of ConsumerInitializationParameters as we will have different client types
  • Provider stops and removes consumer on VSC timeouts (as per original)

Consumer registration has been modified to work with IBC v2:

- Update ibc-go to v10.5.0 with IBC v2 (Eureka) support
- Add IBC v2 application identifiers (ProviderAppID, ConsumerAppID)
- Add IBCPacketHandler interface for v2 client-based routing
- Mark channel/connection keeper interfaces as deprecated
- Remove HandshakeMetadata from wire protocol
- Update IBC module handshake to use version string directly
- Document client-based key mappings in provider types
Provider module:
- Mark channelKeeper and connectionKeeper as deprecated
- Add IBC v2 migration notes to OnAcknowledgementPacket and OnTimeoutPacket

Consumer module:
- Add HighestValsetUpdateID storage for out-of-order packet handling
- Update OnRecvVSCPacket to skip stale packets (IBC v2 compatibility)
- Mark channelKeeper, connectionKeeper, and ibcCoreKeeper as deprecated
- Add key prefix for HighestValsetUpdateIDKey
- Mark template_client as deprecated (per-consumer config recommended)
- Add IBC v2 note to connection_id field
- Regenerate proto files
Add deprecation comments to channel handshake callbacks in both provider
and consumer IBC modules, marking them as IBC v1 patterns that will be
replaced by client-based routing in IBC v2 (Eureka).

Changes:
- Provider ibc_module.go: deprecate channel callbacks (OnChanOpen*, OnChanClose*)
- Consumer ibc_module.go: deprecate channel callbacks and validation
- Consumer genesis.proto: deprecate provider_channel_id and connection_id
- Consumer genesis.go: add IBC v2 migration notes
Add IBC v2 migration documentation to registration flow and genesis handling:

- consumer_lifecycle.go: document RegisterCounterparty as launch trigger
- genesis.go: add notes about client-based vs channel-based routing
- genesis.proto: deprecate channel_id in ConsumerState
- tx.proto: add IBC v2 note to MsgCreateConsumer
Regenerate test mocks to include the new IBCPacketHandler interface
added for IBC v2 packet sending. This interface provides a clean
abstraction for packet sending that can be used with both v1 and v2.
Add IBC v2 (Eureka) packet sending support alongside existing v1 channel-based
routing for backward compatibility during migration.

Changes:
- Add SendIBCPacketV2 function for client-based routing in utils.go
- Add ibcPacketHandler field and SetIBCPacketHandler method to provider keeper
- Add SendVSCPacketsToChainV2 for v2 packet sending
- Update SendVSCPackets to try v2 routing when no channel exists
- Update field count validation to 16 (with optional ibcPacketHandler)

The provider now supports dual-mode operation:
1. Channel-based (v1): Used when consumer has an established channel
2. Client-based (v2): Used when consumer has a client but no channel
Add IBC v2 callback handlers for processing acknowledgements and timeouts
using client-based routing instead of channel-based routing.

New handlers:
- OnAcknowledgementPacketV2: handles acks using client ID lookup
- OnTimeoutPacketV2: handles timeouts using client ID lookup

These handlers use GetClientIdToConsumerId for reverse lookup from
client ID to consumer ID, enabling proper consumer identification
in the IBC v2 routing model.
Add IBC v2 client-based packet reception handler for the consumer module.

Changes:
- Add OnRecvVSCPacketV2 for client-based VSC packet handling
- Add ErrInvalidProviderClient error for v2 client validation
- Provider identification via client ID instead of channel ID
- Maintains out-of-order packet handling from v1

The consumer now supports dual-mode packet reception:
1. Channel-based (v1): OnRecvVSCPacket with channel validation
2. Client-based (v2): OnRecvVSCPacketV2 with client validation
Implement IBCModuleV2 for both provider and consumer that handles
IBC v2 (Eureka) client-based routing:

Provider (ibc_module_v2.go):
- OnSendPacket: validates payload and logs VSC packet sending
- OnRecvPacket: rejects packets (provider only sends, doesn't receive)
- OnTimeoutPacket: triggers consumer removal via OnTimeoutPacketV2
- OnAcknowledgementPacket: handles acks via OnAcknowledgementPacketV2

Consumer (ibc_module_v2.go):
- OnSendPacket: rejects (consumer doesn't send packets in VAAS)
- OnRecvPacket: processes VSC packets via OnRecvVSCPacketV2
- OnTimeoutPacket/OnAcknowledgementPacket: logs unexpected calls

These modules can be registered with IBC v2's router using
application identifiers (vaas/provider, vaas/consumer) instead
of port/channel pairs.
Add comprehensive tests for IBC v2 (Eureka) functionality:

Consumer tests (relay_test.go):
- TestOnRecvVSCPacketV2: Tests client-based packet reception
  and provider client establishment
- TestOnRecvVSCPacketV2OutOfOrder: Tests out-of-order packet
  handling where older packets are acknowledged but ignored

Provider tests (relay_test.go - new file):
- TestOnAcknowledgementPacketV2: Tests error ack handling
  triggers consumer removal
- TestOnTimeoutPacketV2: Tests timeout triggers consumer removal
- TestClientIdToConsumerIdMapping: Tests bidirectional mapping

These tests verify the IBC v2 client-based routing behavior
and out-of-order packet handling for VSC packets.
Add compile-time checks to ensure IBCModuleV2 types implement
the api.IBCModule interface from ibc-go v10:

- Provider IBCModuleV2 verified against api.IBCModule
- Consumer IBCModuleV2 verified against api.IBCModule

This ensures the v2 modules are correctly implemented and will
fail at compile time if the interface changes.
Add test for the HighestValsetUpdateID getter/setter which is used
in IBC v2 to track the highest processed valset update ID for
out-of-order packet handling.
Add tests for the provider's IBC v2 packet sending functionality:

- TestSendVSCPacketsToChainV2NoHandler: Verifies graceful handling
  when no IBC packet handler is configured (packets remain queued)
- TestSendVSCPacketsToChainV2WithHandler: Verifies packets are sent
  correctly via the mock handler and deleted after successful send

These tests verify the v2 packet sending path works correctly with
the IBCPacketHandler interface.
Add v2 version of provider info query that works with client-based
routing:

- GetProviderInfoV2: Returns provider info using client ID instead
  of channel/connection (which don't exist in IBC v2 Eureka model)
- QueryProviderInfo: Updated to try v2 first, then fall back to v1
  for backward compatibility

This allows consumers using IBC v2 to query provider information
even without channel-based connections.
Add comprehensive integration tests for IBC v2 functionality:

Provider tests (ibc_v2_integration_test.go):
- TestIBCV2FullVSCFlow: Complete VSC packet flow with mock handler
- TestIBCV2MultipleConsumers: Sending to multiple consumers
- TestIBCV2ConsumerRemovalOnTimeout: Timeout triggers removal
- TestIBCV2ConsumerRemovalOnErrorAck: Error ack triggers removal
- TestIBCV2DualModeRouting: v2 routing when no channel exists

Consumer tests (ibc_v2_integration_test.go):
- TestIBCV2ConsumerFullVSCFlow: Complete VSC reception flow
- TestIBCV2ConsumerOutOfOrderHandling: Late packets ignored
- TestIBCV2ConsumerRejectsUnknownProvider: Security validation
- TestIBCV2ConsumerProviderInfoQuery: v2 query support
- TestIBCV2ConsumerDuplicatePacketHandling: Duplicate rejection

These tests verify end-to-end IBC v2 behavior including edge cases.
Add documentation for IBC v2 (Eureka) support:

- Feature comparison table (v1 vs v2)
- IBC v2 benefits (simpler setup, out-of-order handling)
- Integration code example for app wiring
- Application IDs (vaas/provider, vaas/consumer)

This helps users understand and integrate IBC v2 routing.
Add comprehensive documentation for IBC v2 (Eureka) support:
- API reference with all queries and messages
- Deployment guide for provider and consumer chains
- Example configurations for genesis and messages
- Updated proto comments for IBC v2 compatibility notes
Added //nolint:staticcheck for GetTemplateClient (left for compatibility reasons) since TemplateClient is deprecated
@julienrbrt julienrbrt self-requested a review February 9, 2026 17:05
vaastypes.EventTypeTimeout,
sdk.NewAttribute(sdk.AttributeKeyModule, providertypes.ModuleName),
sdk.NewAttribute("source_client", sourceClient),
sdk.NewAttribute("sequence", string(rune(sequence))),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses string(rune(sequence)) instead of numeric formatting, producing characters (e.g. "A") instead of sequence numbers.

Suggested change
sdk.NewAttribute("sequence", string(rune(sequence))),
sdk.NewAttribute("sequence", strconv.FormatUint(sequence, 10)),

vaastypes.EventTypePacket,
sdk.NewAttribute(sdk.AttributeKeyModule, providertypes.ModuleName),
sdk.NewAttribute("source_client", sourceClient),
sdk.NewAttribute("sequence", string(rune(sequence))),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses string(rune(sequence)) will produce characters (e.g. "A") instead of sequence numbers

Suggested change
sdk.NewAttribute("sequence", string(rune(sequence))),
sdk.NewAttribute("sequence", strconv.FormatUint(sequence, 10)),

return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest,
"invalid destination port: expected %s, got %s", vaastypes.ConsumerAppID, payload.DestinationPort)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to validate the message signer? signer.String() != im.keeper.GetAuthority()

// In v2, acknowledgements are in a different format
// For now, we check if the first byte indicates success (1) or failure (0)
ackError := ""
if len(acknowledgement) > 0 && acknowledgement[0] == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the IBC v2, there is a different way to handle this error:

if bytes.Equal(acknowledgement, channeltypesv2.ErrorAcknowledgement[:]) {
	ackError = "error acknowledgement received"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants