Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7f13f2b
feat(app): wire IBC v2 (Eureka) transfer stack and router
aluque-peersyst Jul 23, 2026
f0554da
test(ibc): add two-chain ibctesting harness and IBC v2 coverage
aluque-peersyst Jul 30, 2026
4d865fd
fix(app): enforce rate limits on outbound v1 transfers
aluque-peersyst Jul 30, 2026
e0c129b
feat(cbdc): add a governance corridor pause and guard unquotaed v2 sends
aluque-peersyst Jul 30, 2026
6f14919
feat(qbftclient): light client for Besu/QBFT counterparties
aluque-peersyst Jul 30, 2026
4087501
feat(qbftclient): prover, qbftinit and qbftrelay
aluque-peersyst Jul 30, 2026
8de7017
feat(cmd): v2relay break-glass tool and three-chain devnet harness
aluque-peersyst Jul 30, 2026
be20873
chore(deps): bump xrplevm/evm to v0.6.1-xrplevm.1
aluque-peersyst Jul 30, 2026
498331f
fix(qbftclient): read the Besu chain id from the node in live tests
aluque-peersyst Jul 30, 2026
0ac329c
fix(qbftclient): lengthen ClientType so packets can be received
aluque-peersyst Jul 30, 2026
c78bd09
feat(scripts): Besu/QBFT devnet and a Solidity->Go packet converter
aluque-peersyst Jul 30, 2026
5720d47
fix(scripts): seed inbound voucher metadata so tickers and decimals s…
aluque-peersyst Jul 30, 2026
bfbb85a
feat(qbftrelay): add -as-timeout, and prove the timeout leg end to end
aluque-peersyst Jul 30, 2026
f3a7822
feat(packetconv): reverse conversion, and prove the return leg end to…
aluque-peersyst Jul 30, 2026
a2e2324
fix(genesis): expedited_min_deposit was unfundable; record the genesi…
aluque-peersyst Jul 30, 2026
a766d76
chore(git): ignore pilot node homes and cbdcd backups
aluque-peersyst Jul 31, 2026
bdd02df
feat(cmd): sp1fixture — build an SP1 update-client fixture from a liv…
aluque-peersyst Jul 31, 2026
603f7f4
fix(besu-devnet): implement DEC-21's retention instead of approximati…
aluque-peersyst Jul 31, 2026
8ac1d4b
test: run the unit tests CI was skipping
aluque-peersyst Jul 31, 2026
f6c8827
feat(corridor): attestor sidecar, automated relaying, and the proof-a…
aluque-peersyst Jul 31, 2026
3ef9bf0
feat(corridor): generated proof-api types for the ibc-relayer shim
aluque-peersyst Jul 31, 2026
f229243
fix(corridord): receipt check hashed the wrong thing, and failed open
aluque-peersyst Jul 31, 2026
7c15d07
fix(corridor): two defects the security review found in my own work
aluque-peersyst Jul 31, 2026
f4b2542
fix(corridord): temp-file race on the signing path, and an unfiltered…
aluque-peersyst Jul 31, 2026
691f504
chore: F12 cleanups, with the seen-map trade-off made explicit
aluque-peersyst Jul 31, 2026
a74e1a9
fix(corridor): paginate tx_search, and bind the attestor to one target
aluque-peersyst Jul 31, 2026
d21ab16
fix(qbftattestor): make the freeze guard durable and detect a re-genesis
aluque-peersyst Jul 31, 2026
1a04dbe
fix(corridor): give the Besu escrow a refund path
aluque-peersyst Jul 31, 2026
605de98
feat(contracts): bring HondurasCBDC.sol into the repo
aluque-peersyst Jul 31, 2026
cb3e402
fix: CLI mint/burn, Besu log-range limit, and a dead refund path
aluque-peersyst Jul 31, 2026
90fc536
feat(qbftproofapi): proof-API shim so cosmos/ibc-relayer can drive th…
aluque-peersyst Jul 31, 2026
1e5dd76
docs(corridor): a deploy script for the Besu side, and the inputs it …
aluque-peersyst Aug 6, 2026
f3cda6b
feat(corridor): relay packets automatically in both directions
aluque-peersyst Aug 6, 2026
dd312e9
feat(corridor): configuration for cosmos/ibc-relayer against the Besu…
aluque-peersyst Aug 6, 2026
7c36924
feat(corridor): one command to bring up a leg, refusing the mistakes …
aluque-peersyst Aug 6, 2026
4a390fc
fix(corridor): make the deploy guards correct on their own terms
aluque-peersyst Aug 6, 2026
b0debe4
refactor(corridor): put the deploy script where it belongs, and drop …
aluque-peersyst Aug 6, 2026
f3f545e
feat(cbdc): gov-gated MsgSetDenomMetadata, with a display guard the S…
aluque-peersyst Aug 7, 2026
33829f2
feat(qbftclient): AckMsgs and TimeoutMsgs in relaytx, and route qbftr…
aluque-peersyst Aug 7, 2026
ab03c81
feat(qbftproofapi): serve ack and timeout in both proof directions
aluque-peersyst Aug 7, 2026
c397d94
fix(app): BaseDenom is ahnl, the denom the issuer stack actually issues
aluque-peersyst Aug 7, 2026
4f88748
fix(scripts): seed metadata under the destination's client id, and sp…
aluque-peersyst Aug 7, 2026
84db8da
feat(corridor): autorelay loop, Scenario B relayer config, and ignore…
aluque-peersyst Aug 7, 2026
1bf22a5
feat(attestor): a Signer seam, and speak the attestor's own protocol
aluque-peersyst Aug 17, 2026
a389be3
feat(qbftproofapi): the guards a stateless attestor cannot provide
aluque-peersyst Aug 17, 2026
bf7a3d0
feat(qbftaggregator): m-of-n fan-out that refuses divergence
aluque-peersyst Aug 17, 2026
14a8161
feat(corridor): run upstream cosmos/ibc-attestor, and the tooling the…
aluque-peersyst Aug 17, 2026
c60f0bf
fix(corridor): a build target that exists, and docs that name the liv…
aluque-peersyst Aug 17, 2026
b70b5a7
chore: satisfy the linter across the branch
aluque-peersyst Aug 17, 2026
39151a3
Merge branch 'honduras' into feat/add-ibc-v2-to-node
aluque-peersyst Aug 18, 2026
9822c73
fix(qbftproofapi): repair a torn guard log instead of forgetting heights
aluque-peersyst Aug 19, 2026
5114ce7
fix(corridord): fail closed when an abci query fails
aluque-peersyst Aug 19, 2026
8c020fc
fix(qbftclient): bound seal recovery by the trusted validator set
aluque-peersyst Aug 19, 2026
f8c516e
fix(qbftaggregator): require distinct attestors to meet the threshold
aluque-peersyst Aug 19, 2026
1e1f9ce
fix(attestcheck): guard the chain-height underflow before subtracting
aluque-peersyst Aug 19, 2026
b64f61a
feat(cbdc): emit a corridor pause event at the governance action
aluque-peersyst Aug 19, 2026
f49683b
fix(qbftclient): clamp counterparty-supplied seconds instead of wrapping
aluque-peersyst Aug 19, 2026
38d0eee
feat(corridor): keep key material outside the worktree
aluque-peersyst Aug 19, 2026
cefc946
chore(app): shorten the IBC v2 wiring comments
aluque-peersyst Aug 19, 2026
b3e3a9c
chore: ignore working docs and widen the key globs
aluque-peersyst Aug 19, 2026
f3bd3b3
docs(app): trim the BaseDenom comment
aluque-peersyst Aug 19, 2026
8056479
docs(corridor): note which chain id the running rig uses
aluque-peersyst Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,46 @@ release/


.hnld/
.hnld-*/
.hnld.bak-*/
# Node homes from before the cbdcd -> hnld rename; still on disk locally.
.cbdcd/
.cbdcd-*/
.cbdcd.bak-*/
*.out
*.html

bin/
bin/
# The same binaries when a build runs without -o bin/ and drops them in the repo
# root instead -- `go build ./...` at the root does this for every main package.
# Anchored so only the build output is caught, not the cmd/ package directories
# that share these names. Listed as they occur rather than pre-emptively.
/corridord
/qbftattestor
/qbftproofapi
.claude/

# Per-run corridor state: attestor logs, seen-set, relay height cursors. Written
# under $PWD by scripts/corridor/{up-corridor,autorelay}.sh (STATE_ROOT), so it
# lands in the repo root whenever the corridor is driven from here.
.corridor/

# relayer signing keys — never commit
# Filled-in relayer signing keys, one file per corridor leg. Glob rather than a
# single name: a second leg means a second keys file, and a private key that is
# only ignored if someone remembers to extend this list is not ignored.
scripts/corridor/relayer-keys*.json*
!scripts/corridor/relayer-keys.example.json

# attestor signing keys — never commit, and never lose either. The attestor set is
# fixed in AttestationLightClient's constructor with no setter, so a key that only
# ever existed in a shell scrollback costs a light-client redeploy to replace.
scripts/corridor/attestor-key*.json*
# The same key in the Web3 keystore form cosmos/ibc-attestor reads, plus the
# password that opens it. Both are as sensitive as the hex above: together they
# ARE the hex, and separately neither is useful.
scripts/corridor/attestor-keystore*


# Working docs — kept locally, deliberately untracked
docs/*.md
8 changes: 8 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ linters-settings:
suggest-new: true
misspell:
locale: US
ignore-words:
# Not prose: `Misbehaviour` is a protobuf-generated type in
# qbftclient.pb.go, registered in x/qbftclient/codec.go, and it spells the
# ibc-go interface methods this module must implement --
# CheckForMisbehaviour and UpdateStateOnMisbehaviour. Upstream uses the
# British form, so it is an external contract, not a choice. Prose keeps
# the US locale; only the identifier is exempt.
- Misbehaviour
nolintlint:
allow-unused: false
allow-leading-space: true
Expand Down
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ RUN make build


FROM base AS integration
RUN make lint
# Unit tests -- test-unit, not test-poa: the latter runs ./x/poa/... only, which
# left x/qbftclient, x/cbdc and app/ibc/corridorpause unenforced by CI.
RUN make test-unit
# Integration tests
RUN make test-integration
# Simulation tests
# TODO: Restore simulation tests if possible
# RUN make test-sim-benchmark-simulation
# RUN make test-sim-full-app-fast

RUN touch /test.lock

FROM golang:1.23.8 AS release
Expand Down
25 changes: 23 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ install: go.sum
build:
go build $(BUILD_FLAGS) -o ./bin/hnld ./cmd/hnld

# The operator binaries a corridor leg needs, on top of the chain daemon. A
# separate target rather than more lines in `build`: that target means "the chain
# daemon" to scripts/ibcv2-devnet/up.sh and to the runbook's T3.2, and
# build-rocksdb recurses into it — a corridor tool has no business being rebuilt
# by a RocksDB chain build.
#
# qbftattestor is deliberately absent: the attestor runs from a published image
# (DEC-32 adopted cosmos/ibc-attestor), and cmd/qbftattestor is the standby path.
build-corridor: build
go build $(BUILD_FLAGS) -o ./bin/qbftinit ./cmd/qbftinit
go build $(BUILD_FLAGS) -o ./bin/qbftproofapi ./cmd/qbftproofapi
go build $(BUILD_FLAGS) -o ./bin/attestcheck ./cmd/attestcheck

build-rocksdb:
# Make sure to run this command with root permission
CGO_ENABLED=1 CGO_CFLAGS="-I/usr/include" \
Expand Down Expand Up @@ -132,20 +145,28 @@ lint-fix:
### Testing ###
###############################################################################
EXCLUDED_POA_PACKAGES=$(shell go list ./x/poa/... | grep -v /x/poa/testutil | grep -v /x/poa/client | grep -v /x/poa/simulation | grep -v /x/poa/types)
EXCLUDED_UNIT_PACKAGES=$(shell go list ./... | grep -v tests | grep -v testutil | grep -v tools | grep -v app | grep -v docs | grep -v cmd | grep -v /x/poa/testutil | grep -v /x/poa/client | grep -v /x/poa/simulation | grep -v /x/poa/types)
# Anchored on /app so only the app package itself is dropped -- its sole test is
# TestFullAppSimulation, which needs the -Enabled/-NumBlocks/-Params flags the
# test-sim-* targets pass and panics without them. The unanchored filter this
# replaces also dropped app/ibc/corridorpause, i.e. the corridor pause middleware.
EXCLUDED_UNIT_PACKAGES=$(shell go list ./... | grep -v tests | grep -v testutil | grep -v tools | grep -v '/app$$' | grep -v docs | grep -v cmd | grep -v /x/poa/testutil | grep -v /x/poa/client | grep -v /x/poa/simulation | grep -v /x/poa/types)

mocks:
@echo "--> Installing mockgen"
go install github.com/golang/mock/mockgen@v1.6.0
@echo "--> Generating mocks"
@./scripts/mockgen.sh

test: test-poa test-integration test-sim-benchmark-simulation test-sim-full-app-fast
test: test-unit test-integration test-sim-benchmark-simulation test-sim-full-app-fast

test-integration:
@echo "--> Running integration testsuite"
@go test -mod=readonly -tags=test -v ./tests/integration

test-unit:
@echo "--> Running unit tests"
@go test $(EXCLUDED_UNIT_PACKAGES)

test-poa:
@echo "--> Running POA tests"
@go test $(EXCLUDED_POA_PACKAGES)
Expand Down
47 changes: 47 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
"github.com/peersyst/cbdc-node/app/ante"
"github.com/peersyst/cbdc-node/app/ibc/corridorpause"
"github.com/peersyst/cbdc-node/app/ibc/ratelimitv2guard"

"github.com/ethereum/go-ethereum/common"

Expand All @@ -38,6 +40,7 @@ import (
"github.com/cosmos/gogoproto/proto"
ratelimit "github.com/cosmos/ibc-apps/modules/rate-limiting/v10"
ratelimittypes "github.com/cosmos/ibc-apps/modules/rate-limiting/v10/types"
ratelimitv2 "github.com/cosmos/ibc-apps/modules/rate-limiting/v10/v2"
ibcclienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
ibcconnectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types"
ibctesting "github.com/cosmos/ibc-go/v10/testing"
Expand Down Expand Up @@ -123,6 +126,7 @@ import (

ibc "github.com/cosmos/ibc-go/v10/modules/core"
ibcporttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types"
ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api"
ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported"
ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper"

Expand All @@ -132,12 +136,15 @@ import (
cbdctypes "github.com/peersyst/cbdc-node/x/cbdc/types"
poakeeper "github.com/peersyst/cbdc-node/x/poa/keeper"
poatypes "github.com/peersyst/cbdc-node/x/poa/types"
"github.com/peersyst/cbdc-node/x/qbftclient"
qbfttypes "github.com/peersyst/cbdc-node/x/qbftclient/types"

srvflags "github.com/cosmos/evm/server/flags"

"github.com/cosmos/evm/x/erc20"
erc20keeper "github.com/cosmos/evm/x/erc20/keeper"
erc20types "github.com/cosmos/evm/x/erc20/types"
erc20v2 "github.com/cosmos/evm/x/erc20/v2"
"github.com/cosmos/evm/x/feemarket"
feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper"
feemarkettypes "github.com/cosmos/evm/x/feemarket/types"
Expand All @@ -151,6 +158,7 @@ import (
transfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer"
transferkeeper "github.com/cosmos/ibc-go/v10/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
transferv2 "github.com/cosmos/ibc-go/v10/modules/apps/transfer/v2"

// Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
Expand Down Expand Up @@ -556,6 +564,14 @@ func New(
)
app.TransferKeeper.SetAddressCodec(evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()))

// Route v1 outbound packets through the rate limit keeper, which implements
// ICS4Wrapper. Constructed with the channel keeper above, the transfer keeper
// would send straight to core IBC and outbound quotas would never be applied
// (inbound is unaffected: it runs through the IBCModule stack). Only the v1
// send path uses the ICS4Wrapper; v2 accounting happens in ratelimitv2's
// OnSendPacket, so this does not double count.
app.TransferKeeper.WithICS4Wrapper(app.RateLimitKeeper)

transferModule := transfer.NewAppModule(app.TransferKeeper)
// Create the app.ICAHostKeeper
app.ICAHostKeeper = icahostkeeper.NewKeeper(
Expand Down Expand Up @@ -642,12 +658,38 @@ func New(
AddRoute(ibctransfertypes.ModuleName, transferStack)
app.IBCKeeper.SetRouter(ibcRouter)

/**** IBC V2 ****/

// create IBC v2 transfer stack from bottom to top of stack, mirroring v1
var transferStackV2 ibcapi.IBCModule
transferStackV2 = transferv2.NewIBCModule(app.TransferKeeper)
transferStackV2 = ratelimitv2.NewIBCMiddleware(app.RateLimitKeeper, transferStackV2)
// ratelimitv2 passes v2 sends with no client-keyed quota silently; the guard
// emits an event and logs them, without blocking the packet.
transferStackV2 = ratelimitv2guard.NewIBCMiddleware(app.RateLimitKeeper, transferStackV2)
transferStackV2 = erc20v2.NewIBCMiddleware(transferStackV2, app.Erc20Keeper)

// Gov emergency stop per corridor, outermost so a paused client is refused
// before anything escrows, mints or converts. x/cbdc's issuance_paused does not
// reach IBC, and would stop domestic transfers too.
transferStackV2 = corridorpause.NewIBCMiddleware(app.CbdcKeeper, transferStackV2)

// Create static IBC v2 router, add transfer route, then set it (SetRouterV2 does not seal)
ibcRouterV2 := ibcapi.NewRouter()
ibcRouterV2.AddRoute(ibctransfertypes.PortID, transferStackV2)
app.IBCKeeper.SetRouterV2(ibcRouterV2)

clientKeeper := app.IBCKeeper.ClientKeeper
storeProvider := app.IBCKeeper.ClientKeeper.GetStoreProvider()

tmLightClientModule := ibctm.NewLightClientModule(appCodec, storeProvider)
clientKeeper.AddRoute(ibctm.ModuleName, &tmLightClientModule)

// Besu/QBFT counterparty light client. Needs no ibc-go change (AddRoute takes
// any exported.LightClientModule) and no param update (AllowedClients wildcard).
qbftLightClientModule := qbftclient.NewLightClientModule(appCodec, storeProvider)
clientKeeper.AddRoute(qbfttypes.ClientType, &qbftLightClientModule)

/**** Module Hooks ****/

// register hooks after all modules have been initialized
Expand Down Expand Up @@ -719,6 +761,11 @@ func New(
app.BasicModuleManager.RegisterLegacyAminoCodec(cdc)
app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)

// The QBFT light client has no AppModule (no genesis, no state outside the
// client store), so its proto types are registered here; without this the codec
// cannot unmarshal them into ibc-go's interface types.
qbftclient.RegisterInterfaces(interfaceRegistry)

// NOTE: upgrade module is required to be prioritized
app.mm.SetOrderPreBlockers(
upgradetypes.ModuleName,
Expand Down
143 changes: 143 additions & 0 deletions app/ibc/corridorpause/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Package corridorpause gives governance an emergency stop for an IBC corridor.
//
// Why it exists: x/cbdc's issuance_paused switch is checked only in the module's
// own mint and burn path (keeper/mint.go, keeper/burn.go). It does not touch the
// transfer module, IBC, or the bank send path — so with issuance paused, the
// central bank cannot mint, while tokens continue to flow across every corridor.
// For an incident where the corridor itself is the problem, the switch everyone
// reaches for did nothing.
//
// The levers that existed before this one were all wrong in some way: emptying
// allowed_relayers works but is signed by the client creator rather than
// governance; rate limits are percentage quotas meant for shaping flow, and
// cannot exist before a denom has supply; freezing the client needs genuine
// misbehavior evidence; and disabling bank sends for the denom also stops every
// domestic transfer.
//
// This middleware is the missing lever: gov-controlled, per-corridor, and it
// stops both directions.
package corridorpause

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types"
"github.com/cosmos/ibc-go/v10/modules/core/api"
)

// EventTypeRecvPaused is emitted when an inbound packet is rejected on a paused
// corridor. ibc-go runs OnRecvPacket in a cached context and, on failure,
// discards the cache but re-emits its events through ConvertToErrorEvents,
// which prefixes both the type and every attribute key. What lands on chain is
// therefore type "ibccallbackerror-ibc_corridor_recv_paused" with attributes
// "ibccallbackerror-client_id" and "ibccallbackerror-sequence" -- alarms must
// subscribe to the prefixed names; the middleware cannot avoid the prefix.
//
// The send side deliberately emits nothing: OnSendPacket refuses by returning
// an error, which fails the whole transaction, and baseapp keeps only ante
// events for a failed tx -- anything emitted by the message itself is dropped.
// x/cbdc emits cbdc_corridor_pause at the governance action instead, which is
// the reliable signal for both directions.
const (
EventTypeRecvPaused = "ibc_corridor_recv_paused"
AttributeKeyClientID = "client_id"
AttributeKeySequence = "sequence"
)

// ParamsGetter is the slice of the cbdc keeper this middleware needs. Keeping it
// to one method means the middleware can be tested without a keeper.
type ParamsGetter interface {
IsIBCClientPaused(ctx sdk.Context, clientID string) bool
}

var _ api.IBCModule = (*IBCMiddleware)(nil)

// IBCMiddleware refuses packets on paused corridors.
type IBCMiddleware struct {
app api.IBCModule
params ParamsGetter
}

// NewIBCMiddleware wraps app so both packet directions honor the pause.
func NewIBCMiddleware(params ParamsGetter, app api.IBCModule) IBCMiddleware {
return IBCMiddleware{app: app, params: params}
}

// OnSendPacket refuses to originate a transfer on a paused corridor.
//
// Returning an error here fails the sending transaction, so nothing is escrowed
// and the sender keeps their funds.
func (im IBCMiddleware) OnSendPacket(
ctx sdk.Context,
sourceClient string,
destinationClient string,
sequence uint64,
payload channeltypesv2.Payload,
signer sdk.AccAddress,
) error {
if im.params.IsIBCClientPaused(ctx, sourceClient) {
return fmt.Errorf("ibc corridor %s is paused by governance", sourceClient)
}
return im.app.OnSendPacket(ctx, sourceClient, destinationClient, sequence, payload, signer)
}

// OnRecvPacket rejects an inbound transfer on a paused corridor.
//
// It returns a *failed* recv result rather than an error, which is the important
// choice: a failure acknowledgement travels back to the counterparty and refunds
// its sender. Erroring instead would leave the packet stuck until it timed out,
// holding the sender's funds in escrow on the other chain for the duration.
//
// The destination client is the one checked here — that is this chain's name for
// the corridor, the same id governance pauses.
func (im IBCMiddleware) OnRecvPacket(
ctx sdk.Context,
sourceClient string,
destinationClient string,
sequence uint64,
payload channeltypesv2.Payload,
relayer sdk.AccAddress,
) channeltypesv2.RecvPacketResult {
if im.params.IsIBCClientPaused(ctx, destinationClient) {
ctx.EventManager().EmitEvent(sdk.NewEvent(
EventTypeRecvPaused,
sdk.NewAttribute(AttributeKeyClientID, destinationClient),
sdk.NewAttribute(AttributeKeySequence, fmt.Sprint(sequence)),
))
return channeltypesv2.RecvPacketResult{Status: channeltypesv2.PacketStatus_Failure}
}
return im.app.OnRecvPacket(ctx, sourceClient, destinationClient, sequence, payload, relayer)
}

// OnTimeoutPacket is deliberately not gated.
//
// A timeout refunds a sender whose packet was never delivered. Blocking it while
// paused would strand exactly the funds the pause is meant to protect.
func (im IBCMiddleware) OnTimeoutPacket(
ctx sdk.Context,
sourceClient string,
destinationClient string,
sequence uint64,
payload channeltypesv2.Payload,
relayer sdk.AccAddress,
) error {
return im.app.OnTimeoutPacket(ctx, sourceClient, destinationClient, sequence, payload, relayer)
}

// OnAcknowledgementPacket is deliberately not gated, for the same reason as
// timeouts: an acknowledgement settles a transfer that already happened. Refusing
// it would leave in-flight packets unresolved on both sides, which is worse than
// the state the pause was called to stop.
func (im IBCMiddleware) OnAcknowledgementPacket(
ctx sdk.Context,
sourceClient string,
destinationClient string,
sequence uint64,
acknowledgement []byte,
payload channeltypesv2.Payload,
relayer sdk.AccAddress,
) error {
return im.app.OnAcknowledgementPacket(ctx, sourceClient, destinationClient, sequence, acknowledgement, payload, relayer)
}
Loading
Loading