Skip to content

feat: verifiable downtime evidence with optimistic challenges and consumer pausing - #63

Open
giunatale wants to merge 12 commits into
mainfrom
giunatale/feat/offline-detection
Open

feat: verifiable downtime evidence with optimistic challenges and consumer pausing#63
giunatale wants to merge 12 commits into
mainfrom
giunatale/feat/offline-detection

Conversation

@giunatale

Copy link
Copy Markdown
Contributor

Closes #38

Downtime on a consumer chain is unprovable on the provider, but it is disprovable: a single validator signature for a claimed-missed height, sealed under a light-client-verified header, indicts the evidence source.
This PR builds the downtime pipeline around that asymmetry.

  • Consumers track missed blocks over tumbling windows (x/slashing downtime
    handling becomes log-only) and report a per-window bitmap to the provider.
    Window parameters are provider-owned and distributed via consumer genesis
    and VSC packets, with staged activation
  • The provider verifies and prices the infraction (validator's epoch fee
    share x missed fraction, converted via photon), then queues the slash
    behind a challenge window instead of executing it. DowntimeSlashFraction
    acts as a per-window ceiling (default 0.0001), repeated
    windows queue independently and can compound
  • MsgChallengeConsumerDowntime lets anyone cancel a validator's pending
    slashes by proving a claimed-missed block was actually signed. A
    successful challenge refunds the withheld fee shares (escrowed in the
    consumer fee pool for the window's duration) and moves the consumer to a
    new CONSUMER_PHASE_PAUSED: no VSC packets, fee accrual stopped, resumable
    by governance (MsgResumeConsumer, with a forced snapshot resync), and
    auto-stopped after MaxPauseDuration.
  • Inbound VSC packets are now authenticated by source port and a pinned
    provider chain id.

The first two commits are standalone fixes for 2 pre-existing bugs on main (export at a zero height panicked after any slash & the consumer stored the provider's client id instead of its own)

Full design and operational notes in docs/consumer-downtime.md.

giunatale added 12 commits July 16, 2026 20:32
app.NewContext(true) builds a context from an empty header, so the
export context reported block height 0. x/distribution's
CalculateDelegationRewards replays validator slash events between the
delegation's creation height and the context height, so at height 0 it
replayed none: for any validator slashed after its delegation was
created, the recomputed final stake exceeded the current stake and the
export panicked in prepForZeroHeightGenesis. Use NewContextLegacy with
LastBlockHeight, matching upstream simapp.
…vidence packets

the consumer stored packet.SourceClient (the provider's own client) as
its ProviderClientID on first VSC recv, guarded by a "set once" check.
that value is meaningless for the consumer's own outbound sends -- it
needs packet.DestinationClient, its own client id, which is guaranteed
by ibc-go's RecvPacket to already have a registered counterparty. this
was invisible until now because nothing before the downtime evidence
feature ever needed the consumer to send an IBC v2 packet back to the
provider; the genesis-time self-created client (never linked to a
counterparty by the relayer) was silently latched onto forever, so
every evidence packet failed to send with "counterparty not found".

discovery now resyncs on every accepted VSC packet instead of once, so
a stale value from a placeholder client heals itself.

@julienrbrt julienrbrt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have some tiny nits i'll share, but amazing work! so ACK

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.

feat: handle offline validators on the consumer chain side and punish them on provider

2 participants