docs: correct stale documentation and add operator guides - #67
Conversation
|
Branched from Note for reviewers: this describes the assembled behavior of the sibling feature PRs (light-client punishment, genesis round-trip, client authentication, photon fees), so it reads truthfully once those land. Merging it after those avoids a window where docs are ahead of code. |
- delete the stale fork-era PLAN.old.md and REWRITE_SUMMARY.md and rewrite DESIGN_RATIONALE.md, README.md, and AGENTS.md to match the shipped design (PAUSED phase, provider-side no_valupdates, the fee-pool economics, IBC v2 data flow), and correct docs/consumer-fee-pool.md and consumer-lifecycle.md. - add operator and reference docs: a consumer-launch runbook (with fee-pool funding), a params reference for both modules, key-assignment and equivocation/evidence guides, a validator-obligations overview, a security-model / trust-assumptions doc, and a tests/e2e README. - reflect the shipped punishment and fee behavior: light-client attacks are punished (byzantine signers slashed/jailed/tombstoned, an amnesia attack stops the consumer), and downtime fee exclusion applies to the infraction epoch. - add docs/embedding.md, the host-app wiring checklist for a chain integrating the modules: the provider maccPerms entry (whose omission panics the fee-pool sweep inside BeginBlock at the first consumer deletion and halts the chain), the bank send restriction, the provider staking hooks, governance as the IBC client authority, x/evidence on the provider, the consumer message-filter decorator, the provider consensus-key rotation ante decorator, the no_valupdates substitutions and the ordering constraints, the ibcRouterV2 app-id routes, the fee denom, and the consumer keeper construction order -- each with what breaks and whether the failure is silent or fatal. Say plainly that app/provider demonstrates the full wiring while app/consumer is a reduced reference app, and correct README.md's claim that integration "just means adding the v2 routes". - fix the documented consumer fee-pool address preimage: it is derived from the provider module name (vaasprovider-consumer-fee-pool-<id>), not "provider-", and since NewModuleAddress hashes its input the old string named an unrelated, unprotected account. Tell the reader to read fee_pool_address off the chain instead of deriving it. - drop the governance veto that does not exist: a light-client attack the provider cannot punish stops the consumer terminally, and nothing leaves STOPPED. Also correct the trigger -- it fires on no punishable validator, which covers an all-unbonded byzantine set as well as amnesia. - add docs/events-reference.md and docs/queries-reference.md, and link them plus the previously orphaned security-model.md from the README documentation list. The docs that told operators to "watch the acceptance events" now name them, and ErrDepositTooSmall and ErrSubShareWithdraw are documented. - correct further fee-pool and lifecycle claims: the distribution module account is exempt from the send restriction, so a community-pool spend aimed straight at a pool address is not rejected and lands as unattributable balance; the withdraw escrow cap; the withdraw lock covers PAUSED and DELETED blocks everyone; sweep is available pre-launch; the pool must hold a full epoch fee though only eligible shares are drawn; deletion auto-sweeps the pool and clears six more state items; MsgCreateConsumer requires only chain_id and metadata; MakeConsumerGenesis also seeds the safe-mode threshold and the downtime params; client adoption compares against the last computed set, not the last sent one; fee exclusion applies only to a not-yet-distributed epoch; the previous-downtime-params tolerance runs to evidence-max-age plus the challenge window; and the key-assignment signer rule lives in ValidateBasic. - replace stale line-number citations with symbol references, and fix every CLI example: the subcommand root is vaasprovider/vaasconsumer, not provider/consumer. - document pre-launch consumer retirement and the chain-id release: a new MsgRetireConsumer, signable by the consumer owner or by governance when the owner key is lost, erases a consumer still in REGISTERED or INITIALIZED through the same DeleteConsumerChain teardown, with no STOPPED stopover and no unbonding delay, since no validator ever validated the chain. Cover it in consumer-lifecycle.md (a dedicated section plus the DELETED triggers and the summary table), the launch runbook, the queries/tx table, the events table, and DESIGN_RATIONALE's lifecycle summary. Correct the claim that a deleted consumer's chain id stays reserved forever: deletion now releases it as its last step, so the id is registrable again and consumer-chain reports it empty -- a deleted consumer is identified by consumer_id. Note that a funded pool is swept pro rata to its depositors on retirement, dust to the community pool, so a chain that never launched does not strand its prepaid fees. - document the operator procedure for a provider consensus-key rotation, in key-assignment.md with a pointer from validator-obligations.md: the rotation changes the validator's consumer-side identity only on consumers where it has no assigned consumer key, and for those the provider queues and sends an immediate snapshot instead of waiting for the epoch boundary -- so the node signing key must be swapped at the rotation, since the launch grace period is anchored to spawn time and cannot absorb the misses either way. Say that a rotation onto a key already assigned as some validator's consumer key is refused at transaction admission by the ante decorator, and what that costs on a chain that did not wire it. Spell out where the state lands: assigned keys and their reverse mappings follow the validator, fee bookkeeping follows it regardless of assignment, and downtime acceptance bookkeeping deliberately stays under the pre-rotation address where the validator had no assigned key, because that is the identity the consumer validated under -- so a slash queued before the rotation stays challengeable under the old address. Correct embedding.md, which named the hook's old key-assignment-only migration.
c6f2086 to
cf9e63f
Compare
tbruyelle
left a comment
There was a problem hiding this comment.
A welcome update to the docs, but with a few hallucinations about command names and some errors that need to be fixed.
|
|
||
| ``` | ||
| providerd tx provider challenge-consumer-downtime <consumer-id> <validator-cons-addr> <height> \ | ||
| providerd tx vaasprovider challenge-consumer-downtime <consumer-id> <validator-cons-addr> <height> \ |
There was a problem hiding this comment.
| providerd tx vaasprovider challenge-consumer-downtime <consumer-id> <validator-cons-addr> <height> \ | |
| providerd tx provider challenge-consumer-downtime <consumer-id> <validator-cons-addr> <height> \ |
The provider's commands are still registered under the provider keyword. There's more commands to fix, I haven't marked all of them.
| ([x/vaas/provider/keeper/fees.go](../x/vaas/provider/keeper/fees.go)) builds it | ||
| as: | ||
|
|
||
| fee_pool_address = NewModuleAddress("vaasprovider-consumer-fee-pool-<consumer_id>") |
There was a problem hiding this comment.
| fee_pool_address = NewModuleAddress("vaasprovider-consumer-fee-pool-<consumer_id>") | |
| fee_pool_address = NewModuleAddress("provider-consumer-fee-pool-<consumer_id>") |
types.ModuleName hasn't changed and is still equal to provider, not vaasprovider.
| 3. Each byzantine validator is punished through the shared equivocation path | ||
| (`punishEquivocation`, the same primitive double-voting uses), applying the | ||
| global `InfractionParameters.DoubleSign`: **slash**, **jail**, and | ||
| **tombstone**. An already-tombstoned validator is a no-op, so repeated | ||
| submissions are idempotent. |
There was a problem hiding this comment.
The HandleConsumerMisbehavior doc mentions the contrary:
// VAAS deliberately treats light-client misbehaviour as detection-only: the
// evidence is verified and the byzantine set is logged, but no slashing,
| | `vaas_consumer_fee_pool_withdraw` | `msgServer.WithdrawConsumerFeePool` | `consumer_id`, `depositor`, `recipient`, `amount`, `withdraw_path` -- **no `module`** | Shares burned, tokens returned. `withdraw_path` is `direct` or `community_pool` (the gov clawback). On the gov path `depositor` and `recipient` are the same distribution module address, which is what `withdraw_path` exists to disambiguate. | | ||
| | `vaas_consumer_fee_pool_sweep` | `Keeper.emitSweepEvent` | `consumer_id`, `denom`, `total_distributed`, `dust` -- **no `module`** | One event **per swept denom**, from either `MsgSweepConsumerFeePool` or the auto-sweep on consumer deletion. `dust` is the truncation residue forwarded to the community pool. | | ||
| | `vaas_packet` | provider `IBCModule.OnAcknowledgementPacket` | `module` (`vaasprovider`), `source_client`, `sequence` | A VSC packet was acknowledged by a consumer. The ack status is **not** in the attributes -- an error ack looks the same as a success ack here. | | ||
| | `vaas_timeout` | provider `IBCModule.OnTimeoutPacket` | `module` (`vaasprovider`), `source_client`, `sequence` | A provider-sent VSC packet timed out. | |
There was a problem hiding this comment.
None of provider event names have this vaas_ prefix.
| | Event type | Emitted by | Attributes | Meaning | | ||
| |---|---|---|---| | ||
| | `vaas_consumer_evidence_request` | `Keeper.SendEvidencePackets`, in the consumer `EndBlock` | `module` (`vaasconsumer`), `validator_address`, `window_end_height`, `infraction_type` | A downtime evidence packet was handed to IBC and dequeued. One per packet sent. | | ||
| | `vaas_consumer_evidence_rejected` | `Keeper.DropRejectedEvidencePacket`, from `OnAcknowledgementPacket` | `module` (`vaasconsumer`), `validator_address`, `window_end_height`, `error` (hex-encoded ack bytes) | The provider error-acked the evidence, which is always permanent for that packet, so it is dropped rather than retried. **This is the only signal that evidence was refused** -- the provider emits nothing on a rejection. On an undecodable payload `validator_address` is empty and `window_end_height` is `0`. | |
There was a problem hiding this comment.
This event is not referrenced in the code.
| a full unbonding period. A `STOPPED` or `DELETED` consumer is rejected too. | ||
|
|
||
| **Who can submit:** the consumer's **owner** or the **governance authority** — the same | ||
| owner-or-gov admission `MsgFundConsumerFeePool` and `MsgWithdrawConsumerFeePool` use. |
There was a problem hiding this comment.
This is untrue. Neither the MsgFundConsumerFeePool nor the MsgWithdrawConsumerFeePool has such an owner-or-gov admission.
|
|
||
| The full query surface of both VAAS modules: 18 provider queries and 2 consumer | ||
| queries, each with a CLI command. Every gRPC method has a CLI equivalent and | ||
| vice versa. |
There was a problem hiding this comment.
Incorrect, consumer-liveness is missing from the CLI.
Documentation-only: corrects everything stale and adds the operator guides the
repo was missing.
Corrections
that no longer exists.
DESIGN_RATIONALE.md,README.md,AGENTS.md: rewritten to match theshipped design — the PAUSED lifecycle phase, the provider-side fee-pool
economics (no cross-chain reward distribution), the IBC v2 data flow, the
no_valupdatesmodules being a provider-side concern, global (notper-consumer) infraction parameters, and the removal of features that were
never implemented here.
docs/consumer-fee-pool.md(distribution is per epoch, not per block),docs/consumer-lifecycle.md(actual required fields), anddocs/consumer-downtime.md(fee exclusion applies to the epoch theinfraction falls in).
New guides
step without which a consumer immediately accrues debt.
and validation.
validator that prunes consumer block data cannot assemble a downtime
challenge.
it punishes: content-bound client adoption and the permanent pin (including
the consumer's bootstrap trust-on-first-use window and governance client
recovery as the only re-key path), the punishment matrix for double-signing,
light-client attacks, and downtime, the fee-escrow model, and the explicit
note that an embedding provider chain must wire
x/evidenceorprovider-native double-signs go unpunished.
breaks if it is omitted and whether the failure is silent or fatal. It leads
with the module-account permission whose absence halts the provider at the
first consumer deletion, and covers the staking hooks, the consumer's
message-filter decorator, governance as the IBC client authority,
x/evidence,and the provider ante decorator that rejects a colliding consensus-key
rotation. The reference apps are explained as reference apps — in particular
the consumer app deliberately has no governance module, which is exactly why
client recovery is unusable there.
with its exact attribute keys, and every provider and consumer query with its
CLI command and its gotchas. Two docs previously told operators to "watch the
acceptance events" without naming one.
Corrections worth calling out
preimage is hashed it produced a completely unrelated address rather than a
near miss — anyone deriving a pool address from the docs would have sent funds
to an account the send restriction does not protect. Corrected, with a pointer
to the queries that return the real address instead of deriving it by hand.
escalation as reversible by a governance veto. No such path exists: nothing
moves a consumer out of
STOPPED. Now documented as terminal, which is thedefensible behavior for a chain proven byzantine.
docs/used the wrong subcommand root. All of them arecorrected and machine-checked against the modules' actual command names.