Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 10 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

VAAS (Validator-as-a-Service) is a simplified Interchain Security (ICS) implementation for Cosmos blockchains, derived from [interchain-security](https://github.com/cosmos/interchain-security). It lets a provider chain lease its proof-of-stake security to consumer chains via automatic validator synchronization. All active validators validate all consumers — no opt-in/opt-out.

Supports both IBC v1 (channel-based, ordered) and IBC v2 (client-based, out-of-order). IBC v2 uses application IDs `vaas/provider` and `vaas/consumer` instead of port IDs.
VAAS runs on **IBC v2 only** (client-based, out-of-order). There is no IBC v1 channel handshake; the VAAS modules register on `ibcRouterV2` under application IDs `vaasprovider` and `vaasconsumer` (see [x/vaas/types/keys.go](x/vaas/types/keys.go)). Consumer launch relies on a relayer (ts-relayer in localnet and e2e) creating IBC v2 clients on both sides; the provider then discovers its consumer client at the next epoch boundary.

## Build & Test Commands

Expand All @@ -25,11 +25,11 @@ make proto-format # clang-format
make proto-lint # buf lint

# Localnet (3 terminals, or use localnet-start for all-in-one)
make localnet-start # provider + consumer + Hermes relayer
make localnet-start # provider + consumer + ts-relayer (Docker)
make localnet-clean # stop all, clean data

# E2E (Docker-based)
make docker-build-all # build chain + Hermes images
make docker-build-all # build chain image (ts-relayer image is pulled)
make test-e2e # run e2e suite
```

Expand All @@ -45,7 +45,7 @@ The core protocol lives in `x/vaas/` with two symmetric modules:
- **`x/vaas/consumer/`** — runs on consumer chains. Receives VSC packets, maintains cross-chain validator set, reports evidence back to provider.
- **`x/vaas/types/`** — shared types, errors, constants, and `expected_keepers.go` (interfaces for external dependencies like staking/slashing).

Each module has: `keeper/` (business logic + state), `types/` (data structures + params), `client/cli/` (CLI commands), `module.go`, `ibc_module.go` (v1 callbacks), `ibc_module_v2.go` (v2 callbacks).
Each module has: `keeper/` (business logic + state), `types/` (data structures + params), `client/cli/` (CLI commands), `module.go`, and `ibc_module.go` (IBC v2 callbacks implementing `api.IBCModule` from `ibc-go/v10/modules/core/api`).

Two helper modules replace standard Cosmos modules to prevent automatic validator set updates on consumer chains:

Expand All @@ -62,10 +62,11 @@ Built with `make build-apps` into `build/`.

### Key Data Flow

1. Provider detects staking changes → queues VSC packets (every `blocks_per_epoch` blocks, default 600)
2. VSC packets sent via IBC to all registered consumers
3. Consumer receives packet → calls `ApplyCCValidatorChanges()` to update its validator set
4. Double-voting evidence flows consumer → provider, where per-consumer infraction parameters determine slash/jail
1. Once a consumer reaches `LAUNCHED`, a relayer creates an IBC v2 client on the provider pointing to the consumer (and the counterparty on the other side). The provider discovers this client at the next epoch boundary (`discoverActiveConsumerClient`), it never creates the client itself.
2. Provider computes validator set changes once per epoch (`blocks_per_epoch`, default 600) and queues a VSC packet per launched consumer.
3. Provider sends each queued VSC packet over the discovered IBC v2 client. Packets are out-of-order; the consumer deduplicates via `HighestValsetUpdateID`.
4. Consumer's `OnRecvPacket` calls `ApplyCCValidatorChanges()` and the new set is flushed to CometBFT on the next `EndBlock`.
5. Double-voting / light-client evidence flows consumer → provider via `MsgSubmitConsumerDoubleVoting` / `MsgSubmitConsumerMisbehaviour`; per-consumer infraction parameters determine slash/jail.

### Consumer Lifecycle

Expand All @@ -85,7 +86,7 @@ Under `proto/vaas/`: `v1/` (shared wire types like `ValidatorSetChangePacketData

- **Unit tests**: alongside source in `*_test.go`. Use `testutil/keeper/unit_test_helpers.go` for in-memory keeper setup with `MockedKeepers` (gomock).
- **Mock generation**: `make mocks-gen` from `x/vaas/types/expected_keepers.go` → `testutil/keeper/mocks.go`
- **E2E tests**: `tests/e2e/` — Docker-based, spins up real chains with Hermes relayer.
- **E2E tests**: `tests/e2e/` — Docker-based, spins up real provider/consumer chains plus the `ghcr.io/allinbits/ibc-v2-ts-relayer` container; see [tests/e2e/e2e_tsrelayer_test.go](tests/e2e/e2e_tsrelayer_test.go).

## Lint / Import Ordering

Expand Down
134 changes: 134 additions & 0 deletions DESIGN_RATIONALE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# VAAS Design Rationale

> This document supersedes [`PLAN.old.md`](PLAN.old.md), the original rewrite
> plan drafted before the port from `interchain-security`. `PLAN.old.md` is
> kept for historical reference only; the present document is the
> authoritative statement of why VAAS is shaped the way it is.

This is a forward-facing reference for contributors. For the per-feature
historical diff against the `interchain-security` codebase VAAS was ported
from, see [`REWRITE_SUMMARY.md`](REWRITE_SUMMARY.md); for protocol-level
mechanics, see [`docs/consumer-lifecycle.md`](docs/consumer-lifecycle.md) and
[`AGENTS.md`](AGENTS.md).

VAAS is a **simplified** Interchain Security: a Cosmos provider chain lends
its full validator set to one or more consumer chains, automatically, with no
opt-in/out and no power shaping. The simplification is the product, not a
work-in-progress.

---

## Guiding Principles

1. **All validators validate everything.** There is no per-consumer
selection. The active provider set, capped at
`MaxProviderConsensusValidators`, is the consumer set.
2. **No cross-chain economics inside the protocol.** No reward distribution,
no per-consumer commission rates, no slash throttling, no slash meters.
Consumers stand up their own fee/reward models; the protocol carries only
validator-set state and security signals.
3. **IBC v2 only.** No channel handshake, no ordered channels, no port
reservations. VAAS modules register on `ibcRouterV2` under the application
IDs `vaasprovider` and `vaasconsumer`; consumer launch relies on a relayer
creating the IBC v2 clients and the provider discovering its consumer
client at the next epoch boundary.
4. **Forward-only consumer lifecycle.** `REGISTERED → INITIALIZED → LAUNCHED
→ STOPPED → DELETED`, with a single rollback path (failed launch → back to
`REGISTERED`). Standalone-to-consumer changeover is not currently
supported; see [`docs/consumer-transition.md`](docs/consumer-transition.md)
for the future-work considerations.
5. **Provider authority for control-plane messages.** `OnSendPacket` requires
the keeper's authority as signer; consumers never send packets back
(`OnRecvPacket` on the provider is a failure path; `OnSendPacket` on the
consumer is rejected). Misbehaviour reports travel as ordinary provider
transactions, not IBC packets.

---

## Why the Simplifications

### Removed: Partial Set Security (PSS), Top N, Opt-in, Power Shaping

The `interchain-security` codebase supports renting *subsets* of the
validator set per consumer with caps, allowlists, denylists, priority lists,
and inactive-validator participation (ADR-017). VAAS targets deployments
where the provider guarantees its entire active set to every consumer.
Removing PSS deletes a large surface area: per-validator opt-in state,
per-consumer power-shaping parameters, "has-to-validate" queries, and the
messages that maintain them (`MsgOptIn`, `MsgOptOut`,
`MsgSetConsumerCommissionRate`).

The trade-off is rigidity: a consumer cannot pick a smaller validator set.
That is intentional. Smaller sets do not inherit the BFT assumption of the
full set, there is no assumption that can be made about smaller sets, no
security guarantee. The simplification also drastically reduces the
complexity of the system.

### Removed: Slash Packet Throttling, Slash Meters, Slash Retry

ICS throttles slash packets to bound the impact of a misbehaving or
adversarial consumer on the provider's validator set. VAAS removes the
throttle, the meter, and the retry queue. Consumer-initiated slashing for
downtime is *not currently performed by the provider*; equivocation evidence
(double-sign, light-client) is submitted as a provider transaction
(`MsgSubmitConsumerDoubleVoting`, `MsgSubmitConsumerMisbehaviour`) and
slashed using per-consumer infraction parameters. Downtime slashing via slash
packets is an open design question (see open issues / PRs).

### Removed: Consumer Reward Distribution

ICS pipes a fraction of consumer fees back to the provider as validator
rewards. VAAS leaves the consumer fee model entirely to the consumer chain.
This eliminates a category of cross-chain accounting and the related
provider-side state (reward denom registration, fee pool addressing, etc.).

### Kept: Per-Consumer Infraction Parameters

Each consumer carries its own `infraction_parameters` (double-sign and
downtime slash fractions, jail durations, tombstone flag). This is the one
place per-consumer customisation survives — the protocol cannot decide
slash severity centrally because consumers vary in security profile.

### Kept: Key Assignment

Validators may assign per-consumer consensus keys via
`MsgAssignConsumerKey`. Keys are ed25519 only and prune on unbonding, with
checks that prevent key reuse across consumers.

---

## Active Work and Open Questions

Live work is tracked in GitHub issues and pull requests, not in this file —
this list points to the rough areas, not the specific tickets.

- **Genesis import/export**. Several entry points in the provider and
consumer modules still need correct round-trip support. The provider
`InitGenesis` path uses the chain-ID field as the consumer-id key, which
needs cleaning up.
- **Per-consumer infraction parameters at runtime**. The parameters are
stored per consumer but the equivocation handling path needs to consume
them consistently.
- **Provider-side downtime slashing.** Whether (and how) consumers should be
able to request downtime slashing on the provider is an open design
question; a draft PR proposes a slash-packet-based path.
- **Timeout policy.** A VSC packet timeout currently has heavy consequences
(consumer removal); whether this is the right default is open.
- **Standalone-to-consumer transition.** The `PreVAAS` / `PrevStandaloneChain`
collections and the `standaloneStakingKeeper` plumbing in the consumer
module are dead today but preserved deliberately as a reference for a
future transition implementation; see
[`docs/consumer-transition.md`](docs/consumer-transition.md).

## Explicit Non-Goals

The following are intentionally **not** part of VAAS and should not be added
back without a strong, documented reason:

- Partial Set Security (Top N, opt-in/out, allow/deny lists)
- Per-consumer power shaping (caps, priority lists)
- Slash packet throttling / slash meters
- Cross-chain reward distribution
- Per-consumer commission rates
- IBC v1 channel routing for VAAS messages
- Inactive provider validators participating in consumer security (ADR-017)
7 changes: 7 additions & 0 deletions PLAN.md → PLAN.old.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# VAAS Rewrite Plan

> **Historical document.** This was the original plan drafted *before* the
> port of `interchain-security` into VAAS, when the new module was still
> being scoped. Paths, function names, and tooling assumptions reflect that
> moment and are no longer accurate. It is kept verbatim for archival
> reference. For the current authoritative statement of why VAAS is shaped
> the way it is, see [`DESIGN_RATIONALE.md`](DESIGN_RATIONALE.md).

Rewrite `x/vaas/provider` and `x/vaas/consumer` in a new `vaas` folder as a **new Go module** with package path `github.com/allinbits/vaas`.

---
Expand Down
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@

VAAS allows Cosmos blockchains to lease their proof-of-stake security to consumer chains. All active validators on the provider chain automatically validate all consumer chains - there is no opt-in/opt-out mechanism.

## Features
## IBC v2 only

## IBC v2 support
VAAS uses IBC v2 exclusively — no channel handshake, no port reservations.
The provider and consumer modules register on `ibcRouterV2` under the
application IDs `vaasprovider` and `vaasconsumer`. After a consumer launches,
a relayer (the localnet and e2e suites use
[`ts-relayer`](https://github.com/allinbits/ibc-v2-ts-relayer)) creates an
IBC v2 client on each chain pointing at the counterparty and registers the
path. The provider then discovers its consumer client at the next epoch
boundary; all VSC packets flow over that client. Wiring VAAS into a host app
just means adding the v2 routes — see [`app/provider/app.go`](app/provider/app.go)
and [`app/consumer/app.go`](app/consumer/app.go) for reference.

The VAAS implementation supports IBC v2 only.
IBC v2 is easily wireable by adding the IBC router v2 in a ibc-go >= 10.x.y compatible chain.
## Features

### Kept from ICS

Expand All @@ -37,7 +45,10 @@ IBC v2 is easily wireable by adding the IBC router v2 in a ibc-go >= 10.x.y comp
| Slash Packet Throttling | Simplified slash handling |
| Per-Consumer Commission Rates | Validators use same commission as provider |
| IBC v1 Channel Support | IBC v2 only |
| Standalone-to-Consumer Changeover | Only new chains as consumers |
| Standalone-to-Consumer Changeover | Not currently supported (future work) |

See [docs/consumer-transition.md](docs/consumer-transition.md) for the
consequences and requirements of a future standalone-to-consumer transition.

## Build & Test

Expand All @@ -51,6 +62,15 @@ make docker-build-all
make test-e2e
```

## Documentation

- [Localnet setup](app/README.md) — run a provider, a consumer, and `ts-relayer` locally
- [Consumer lifecycle](docs/consumer-lifecycle.md) — phases, on-chain effects, operator/relayer responsibilities
- [Contributor guide (AGENTS.md)](AGENTS.md) — architecture, build/test commands, code layout
- [Design rationale (DESIGN_RATIONALE.md)](DESIGN_RATIONALE.md) — why VAAS is shaped the way it is
- [Diff vs the ICS codebase VAAS ported from (REWRITE_SUMMARY.md)](REWRITE_SUMMARY.md) — what was removed/kept in the port
- [PLAN.old.md](PLAN.old.md) — the original pre-port rewrite plan, kept for archival reference

## Learn More

- [ICS Documentation](https://cosmos.github.io/interchain-security/)
Expand Down
Loading
Loading