From dc5adb595ad2a2eba8831d806af278aed1fef4d2 Mon Sep 17 00:00:00 2001 From: samricotta <37125168+samricotta@users.noreply.github.com> Date: Fri, 21 Jul 2023 11:05:01 +0200 Subject: [PATCH 1/2] Update docusaurus.config.js (#10) --- docusaurus.config.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index d1dd203e2..4a8eb2c73 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -99,19 +99,6 @@ const config = { type: "docsVersionDropdown", position: "right", dropdownActiveClassDisabled: true, - // versions not yet migrated to docusaurus - dropdownItemsAfter: [ - { - href: "https://docs.cosmos.network/v0.46/", - label: "v0.46", - target: "_self", - }, - { - href: "https://docs.cosmos.network/v0.45/", - label: "v0.45", - target: "_self", - }, - ], }, ], }, From a917c227a9e5d70b746f9f2874d7fd6b6ba52d9c Mon Sep 17 00:00:00 2001 From: samricotta <37125168+samricotta@users.noreply.github.com> Date: Wed, 26 Jul 2023 09:57:52 +0200 Subject: [PATCH 2/2] refactor: Fix formatting and some links (#11) * wip * wip --- docs/develop/advanced-concepts/07-cli.md | 2 +- .../high-level-concepts/00-overview-app.md | 2 +- .../architecture/adr-038-state-listening.md | 2 +- ...r-040-storage-and-smt-state-commitments.md | 2 +- .../{01-intro.md => 00-intro.md} | 0 .../building-modules/01-module-manager.md | 2 +- .../02-messages-and-queries.md | 2 +- docs/integrate/building-modules/06-keeper.md | 2 +- .../building-modules/09-module-interfaces.md | 2 +- docs/integrate/spec/addresses/bech32.md | 2 +- docs/integrate/tooling/01-cosmovisor.md | 2 +- docs/integrate/tooling/03-autocli.md | 2 +- docusaurus.config.js | 2 +- .../version-0.45/develop/_category_.json | 5 + .../{baseapp.md => 00-baseapp.md} | 72 +- .../{transactions.md => 01-transactions.md} | 28 +- .../{context.md => 02-context.md} | 32 +- .../advanced-concepts/{node.md => 03-node.md} | 18 +- .../{store.md => 04-store.md} | 26 +- .../{encoding.md => 05-encoding.md} | 18 +- .../advanced-concepts/{cli.md => 06-cli.md} | 24 +- .../{events.md => 07-events.md} | 28 +- .../{grpc_rest.md => 08-grpc_rest.md} | 14 +- .../advanced-concepts/{ocap.md => 09-ocap.md} | 6 +- .../{telemetry.md => 10-telemetry.md} | 6 +- ...x_middleware.md => 11-runtx_middleware.md} | 4 - .../{simulation.md => 12-simulation.md} | 4 - .../{upgrade.md => 13-upgrade.md} | 8 +- .../develop/advanced-concepts/README.md | 28 - .../{app-anatomy.md => 00-overview-app.md} | 62 +- .../{tx-lifecycle.md => 01-tx-lifecycle.md} | 42 +- ...ery-lifecycle.md => 02-query-lifecycle.md} | 34 +- .../{accounts.md => 03-accounts.md} | 8 +- .../{gas-fees.md => 04-gas-fees.md} | 22 +- .../develop/high-level-concepts/README.md | 17 - .../high-level-concepts/_category_.json | 5 + .../version-0.45/develop/intro/README.md | 16 - .../version-0.45/develop/intro/overview.md | 6 +- .../develop/intro/sdk-app-architecture.md | 8 +- .../version-0.45/develop/intro/sdk-design.md | 18 +- .../develop/intro/why-app-specific.md | 4 - .../version-0.45/integrate/_category_.json | 5 + .../architecture/adr-038-state-listening.md | 2 +- ...r-040-storage-and-smt-state-commitments.md | 2 +- .../{intro.md => 00-intro.md} | 30 +- ...module-manager.md => 01-module-manager.md} | 68 +- ...-queries.md => 02-messages-and-queries.md} | 40 +- .../{msg-services.md => 03-msg-services.md} | 32 +- ...query-services.md => 04-query-services.md} | 22 +- ...-endblock.md => 05-beginblock-endblock.md} | 20 +- .../{keeper.md => 06-keeper.md} | 20 +- .../{invariants.md => 07-invariants.md} | 14 +- .../{genesis.md => 08-genesis.md} | 16 +- ...-interfaces.md => 09-module-interfaces.md} | 18 +- .../{structure.md => 10-structure.md} | 6 +- .../{errors.md => 11-errors.md} | 4 - .../{upgrade.md => 12-upgrade.md} | 6 +- .../{simulator.md => 13-simulator.md} | 2 +- .../integrate/building-modules/README.md | 23 - .../building-modules/_category_.json | 5 + .../version-0.45/integrate/ibc/README.md | 20 - .../integrate/ibc/_category_.json | 5 + .../version-0.45/integrate/ibc/custom.md | 4 - .../version-0.45/integrate/ibc/integration.md | 4 - .../version-0.45/integrate/ibc/overview.md | 2 - .../version-0.45/integrate/ibc/proposals.md | 4 - .../version-0.45/integrate/ibc/relayer.md | 6 +- .../integrate/ibc/upgrades/_category_.json | 5 + .../integrate/ibc/upgrades/developer-guide.md | 4 - .../integrate/ibc/upgrades/quick-guide.md | 4 - .../version-0.45/user/_category_.json | 5 + .../run-node/{keyring.md => 00-keyring.md} | 4 +- .../run-node/{run-node.md => 01-run-node.md} | 2 +- .../{interact-node.md => 02-interact-node.md} | 6 +- .../user/run-node/{txs.md => 03-txs.md} | 2 +- .../run-node/{rosetta.md => 04-rosetta.md} | 0 .../{run-testnet.md => 05-run-testnet.md} | 0 .../user/run-node/_category_.json | 5 + .../version-0.46/develop/_category_.json | 5 + .../develop/advanced-concepts/00-baseapp.md | 52 +- .../advanced-concepts/01-transactions.md | 22 +- .../develop/advanced-concepts/03-context.md | 16 +- .../develop/advanced-concepts/04-node.md | 10 +- .../develop/advanced-concepts/05-store.md | 14 +- .../develop/advanced-concepts/07-encoding.md | 14 +- .../develop/advanced-concepts/08-grpc_rest.md | 8 +- .../develop/advanced-concepts/09-cli.md | 22 +- .../develop/advanced-concepts/10-events.md | 18 +- .../develop/advanced-concepts/11-telemetry.md | 4 - .../develop/advanced-concepts/12-ocap.md | 4 - .../advanced-concepts/13-runtx_middleware.md | 4 - .../advanced-concepts/13-simulation.md | 4 - .../advanced-concepts/14-proto-docs.md | 4 - .../develop/advanced-concepts/15-tips.md | 4 - .../develop/advanced-concepts/16-upgrade.md | 8 +- .../{app-anatomy.md => 00-overview-app.md} | 64 +- .../{tx-lifecycle.md => 01-tx-lifecycle.md} | 44 +- ...ery-lifecycle.md => 02-query-lifecycle.md} | 34 +- .../{accounts.md => 03-accounts.md} | 8 +- .../{gas-fees.md => 04-gas-fees.md} | 22 +- .../develop/high-level-concepts/README.md | 17 - .../high-level-concepts/_category_.json | 5 + .../intro/{overview.md => 00-what-is-sdk.md} | 10 +- ...app-specific.md => 01-why-app-specific.md} | 4 - ...itecture.md => 02-sdk-app-architecture.md} | 8 +- .../intro/{sdk-design.md => 03-sdk-design.md} | 18 +- .../version-0.46/develop/intro/README.md | 16 - .../develop/intro/_category_.json | 5 + .../integrate/CosmWasm/_category_.json | 5 + .../version-0.46/integrate/_category_.json | 5 + .../integrate/architecture/_category_.json | 5 + .../adr-003-dynamic-capability-store.md | 2 +- .../adr-017-historical-header-module.md | 2 +- .../adr-033-protobuf-inter-module-comm.md | 4 +- .../architecture/adr-038-state-listening.md | 2 +- ...r-040-storage-and-smt-state-commitments.md | 4 +- .../integrate/building-modules/00-intro.md} | 34 +- ...module-manager.md => 01-module-manager.md} | 64 +- ...-queries.md => 02-messages-and-queries.md} | 38 +- .../{msg-services.md => 03-msg-services.md} | 22 +- ...query-services.md => 04-query-services.md} | 22 +- ...-endblock.md => 05-beginblock-endblock.md} | 20 +- .../{keeper.md => 06-keeper.md} | 20 +- .../{invariants.md => 07-invariants.md} | 14 +- .../{genesis.md => 08-genesis.md} | 16 +- ...-interfaces.md => 09-module-interfaces.md} | 18 +- .../{structure.md => 11-structure.md} | 6 +- .../{errors.md => 12-errors.md} | 4 - .../{upgrade.md => 13-upgrade.md} | 8 +- .../{simulator.md => 14-simulator.md} | 2 +- .../integrate/building-modules/README.md | 23 - .../building-modules/_category_.json | 5 + .../integrate/ibc/_category_.json | 5 + .../{pre-upgrade.md => 00-pre-upgrade.md} | 0 .../integrate/migrations/README.md | 13 - .../integrate/migrations/_category_.json | 5 + .../integrate/modules/_category_.json | 5 + .../integrate/modules/auth/01_concepts.md | 4 - .../integrate/modules/auth/02_state.md | 4 - .../integrate/modules/auth/03_antehandlers.md | 4 - .../integrate/modules/auth/04_keepers.md | 4 - .../integrate/modules/auth/05_vesting.md | 4 - .../integrate/modules/auth/06_params.md | 4 - .../integrate/modules/auth/07_client.md | 4 - .../integrate/modules/auth/_category_.json | 5 + .../integrate/modules/authz/01_concepts.md | 4 - .../integrate/modules/authz/02_state.md | 4 - .../integrate/modules/authz/03_messages.md | 4 - .../integrate/modules/authz/04_events.md | 4 - .../integrate/modules/authz/05_client.md | 4 - .../integrate/modules/authz/_category_.json | 5 + .../integrate/modules/bank/_category_.json | 5 + .../modules/capability/01_concepts.md | 4 - .../integrate/modules/capability/02_state.md | 4 - .../modules/capability/_category_.json | 5 + .../integrate/modules/crisis/01_state.md | 4 - .../integrate/modules/crisis/02_messages.md | 4 - .../integrate/modules/crisis/03_events.md | 4 - .../integrate/modules/crisis/04_params.md | 4 - .../integrate/modules/crisis/05_client.md | 4 - .../integrate/modules/crisis/_category_.json | 5 + .../modules/distribution/_category_.json | 5 + .../modules/evidence/_category_.json | 5 + .../modules/feegrant/_category_.json | 5 + .../integrate/modules/gov/_category_.json | 5 + .../integrate/modules/mint/_category_.json | 5 + .../integrate/modules/params/_category_.json | 5 + .../modules/slashing/_category_.json | 5 + .../integrate/modules/staking/_category_.json | 5 + .../integrate/modules/upgrade/_category_.json | 5 + .../version-0.46/user/_category_.json | 5 + .../run-node/{keyring.md => 00-keyring.md} | 8 +- .../run-node/{run-node.md => 01-run-node.md} | 10 +- .../{interact-node.md => 02-interact-node.md} | 10 +- .../user/run-node/{txs.md => 03-txs.md} | 6 +- .../run-node/{rosetta.md => 04-rosetta.md} | 4 - .../{run-testnet.md => 05-run-testnet.md} | 4 - .../version-0.46/user/run-node/README.md | 17 - .../user/run-node/_category_.json | 5 + .../version-0.47/develop/_category_.json | 5 + .../develop/advanced-concepts/00-baseapp.md | 99 +- .../advanced-concepts/01-transactions.md | 36 +- .../develop/advanced-concepts/02-context.md | 24 +- .../develop/advanced-concepts/03-node.md | 12 +- .../develop/advanced-concepts/04-store.md | 279 +- .../advanced-concepts/05-interblock-cache.md | 293 ++ .../{05-encoding.md => 06-encoding.md} | 54 +- .../develop/advanced-concepts/07-cli.md | 52 +- .../develop/advanced-concepts/08-events.md | 32 +- .../{06-grpc_rest.md => 09-grpc_rest.md} | 10 +- .../{09-telemetry.md => 11-telemetry.md} | 0 ...x_middleware.md => 12-runtx_middleware.md} | 4 +- .../{12-simulation.md => 13-simulation.md} | 2 +- .../{13-proto-docs.md => 14-proto-docs.md} | 0 .../{14-tips.md => 15-tips.md} | 2 +- .../{15-upgrade.md => 16-upgrade.md} | 6 +- .../develop/advanced-concepts/17-config.md | 24 + .../develop/advanced-concepts/_category_.json | 2 +- .../version-0.47/develop/glossary.md | 57 + .../{00-app-anatomy.md => 00-overview-app.md} | 73 +- .../high-level-concepts/01-tx-lifecycle.md | 67 +- .../high-level-concepts/02-query-lifecycle.md | 35 +- .../high-level-concepts/03-accounts.md | 9 +- .../high-level-concepts/04-gas-fees.md | 21 +- .../high-level-concepts/_category_.json | 2 +- .../develop/intro/00-what-is-sdk.md | 9 +- .../develop/intro/02-sdk-app-architecture.md | 8 +- .../develop/intro/03-sdk-design.md | 12 +- .../version-0.47/integrate/_category_.json | 5 + .../integrate/architecture/PROCESS.md | 20 +- .../integrate/architecture/README.md | 85 +- .../integrate/architecture/_category_.json | 4 +- .../adr-007-specialization-groups.md | 2 +- .../architecture/adr-008-dCERT-group.md | 4 +- ...dr-016-validator-consensus-key-rotation.md | 4 +- .../adr-020-protobuf-transaction-encoding.md | 8 +- .../adr-021-protobuf-query-encoding.md | 6 +- .../adr-022-custom-panic-handling.md | 6 +- .../architecture/adr-024-coin-metadata.md | 1 + ...27-deterministic-protobuf-serialization.md | 2 +- .../architecture/adr-030-authz-module.md | 2 +- .../architecture/adr-031-msg-service.md | 10 +- .../architecture/adr-032-typed-events.md | 10 +- .../adr-033-protobuf-inter-module-comm.md | 24 +- .../architecture/adr-038-state-listening.md | 911 +++-- ...r-040-storage-and-smt-state-commitments.md | 2 +- .../architecture/adr-042-group-module.md | 2 +- .../adr-044-protobuf-updates-guidelines.md | 2 +- .../adr-045-check-delivertx-middlewares.md | 4 +- .../adr-047-extend-upgrade-plan.md | 41 +- .../architecture/adr-049-state-sync-hooks.md | 14 +- .../adr-050-sign-mode-textual-annex1.md | 172 +- .../adr-050-sign-mode-textual-annex2.md | 36 +- .../architecture/adr-050-sign-mode-textual.md | 475 +-- .../adr-053-go-module-refactoring.md | 3 +- .../adr-054-semver-compatible-modules.md | 728 ++++ .../integrate/architecture/adr-055-orm.md | 14 +- .../architecture/adr-057-app-wiring.md | 17 +- .../adr-058-auto-generated-cli.md | 3 + .../architecture/adr-059-test-scopes.md | 31 +- .../architecture/adr-060-abci-1.0.md | 145 +- .../architecture/adr-061-liquid-staking.md | 6 +- .../adr-062-collections-state-layer.md | 117 + .../architecture/adr-063-core-module-api.md | 507 +++ .../architecture/adr-064-abci-2.0.md | 461 +++ .../architecture/adr-065-store-v2.md | 290 ++ .../integrate/architecture/adr-template.md | 47 +- .../integrate/building-apps/00-app-go.md | 1 + .../integrate/building-apps/01-app-go-v2.md | 6 +- .../integrate/building-apps/02-app-mempool.md | 15 +- .../integrate/building-apps/03-app-upgrade.md | 1 + .../integrate/building-apps/_category_.json | 2 +- .../integrate/building-modules/00-intro.md} | 46 +- .../building-modules/01-module-manager.md | 74 +- .../02-messages-and-queries.md | 35 +- .../building-modules/03-msg-services.md | 29 +- .../building-modules/04-query-services.md | 6 +- .../05-beginblock-endblock.md | 16 +- .../integrate/building-modules/06-keeper.md | 16 +- .../building-modules/07-invariants.md | 8 +- .../integrate/building-modules/08-genesis.md | 20 +- .../building-modules/09-module-interfaces.md | 18 +- .../building-modules/11-structure.md | 72 +- .../integrate/building-modules/13-upgrade.md | 4 +- .../building-modules/14-simulator.md | 5 +- .../building-modules/15-depinject.md | 8 +- .../integrate/building-modules/16-testing.md | 44 +- .../building-modules/_category_.json | 2 +- .../building-modules/transaction_flow.svg | 48 + .../integrate/libraries/01-depinject.md | 187 + .../integrate/libraries/02-collections.md | 1119 ++++++ .../integrate/libraries/03-orm.md | 329 ++ .../integrate/libraries/04-packages.md | 39 + .../integrate/libraries/_category_.json | 5 + .../integrate/migrations/01-intro.md | 2 +- .../integrate/migrations/02-upgrading.md | 612 ++++ .../integrate/migrations/_category_.json | 2 +- .../integrate/modules/README.md | 3 + .../integrate/modules/_category_.json | 4 +- .../integrate/modules/auth/1-vesting.md | 618 ++++ .../integrate/modules/auth/2-tx.md | 266 ++ .../integrate/modules/auth/README.md | 705 ++++ .../integrate/modules/authz/README.md | 355 ++ .../integrate/modules/bank/README.md | 950 +++++ .../integrate/modules/circuit/README.md | 115 + .../integrate/modules/consensus/README.md | 7 + .../integrate/modules/crisis/README.md | 110 + .../integrate/modules/distribution/README.md | 1042 ++++++ .../integrate/modules/evidence/README.md | 440 +++ .../integrate/modules/feegrant/README.md | 388 +++ .../integrate/modules/genutil/README.md | 69 + .../integrate/modules/gov/README.md | 2658 ++++++++++++++ .../integrate/modules/group/README.md | 2156 ++++++++++++ .../integrate/modules/mint/README.md | 383 +++ .../integrate/modules/nft/README.md | 89 + .../integrate/modules/params/README.md | 79 + .../integrate/modules/slashing/README.md | 813 +++++ .../integrate/modules/staking/README.md | 3058 +++++++++++++++++ .../integrate/modules/upgrade/README.md | 619 ++++ .../version-0.47/integrate/rfc/PROCESS.md | 62 + .../version-0.47/integrate/rfc/README.md | 34 + .../integrate/rfc/_category_.json | 5 + .../integrate/rfc/rfc-001-tx-validation.md | 25 + .../integrate/rfc/rfc-template.md | 83 + .../version-0.47/integrate/spec/README.md | 25 - .../spec/{SPEC-SPEC.md => SPEC_MODULE.md} | 2 +- .../integrate/spec/SPEC_STANDARD.md | 121 + .../integrate/spec/_category_.json | 4 +- .../integrate/spec/_ics/README.md | 3 - .../integrate/spec/addresses/README.md | 2 +- .../integrate/spec/addresses/bech32.md | 2 +- .../integrate/spec/circuit-breaker/README.md | 16 - .../version-0.47/integrate/spec/ics/README.md | 3 + .../{_ics => ics}/ics-030-signed-messages.md | 2 +- .../integrate/spec/reserve-pool/README.md | 4 - .../integrate/spec/store/README.md | 235 -- .../integrate/tooling/00-protobuf.md | 4 +- .../integrate/tooling/01-cosmovisor.md | 366 ++ .../integrate/tooling/02-confix.md | 130 + .../10-autocli.md => tooling/03-autocli.md} | 4 +- .../version-0.47/integrate/tooling/04-hubl.md | 73 + .../integrate/tooling/05-depinject.md | 169 + .../version-0.47/integrate/tooling/README.md | 11 - .../integrate/tooling/_category_.json | 2 +- .../version-0.47/user/run-node/00-keyring.md | 2 +- .../version-0.47/user/run-node/01-run-node.md | 51 +- .../user/run-node/02-interact-node.md | 14 +- .../version-0.47/user/run-node/03-txs.md | 6 +- .../version-0.47/user/run-node/04-rosetta.md | 122 + .../user/run-node/06-run-production.md | 3 + .../user/run-node/_category_.json | 4 +- .../run-node => validate}/05-run-testnet.md | 2 +- 332 files changed, 23488 insertions(+), 3311 deletions(-) rename docs/integrate/building-modules/{01-intro.md => 00-intro.md} (100%) create mode 100644 versioned_docs/version-0.45/develop/_category_.json rename versioned_docs/version-0.45/develop/advanced-concepts/{baseapp.md => 00-baseapp.md} (82%) rename versioned_docs/version-0.45/develop/advanced-concepts/{transactions.md => 01-transactions.md} (75%) rename versioned_docs/version-0.45/develop/advanced-concepts/{context.md => 02-context.md} (68%) rename versioned_docs/version-0.45/develop/advanced-concepts/{node.md => 03-node.md} (82%) rename versioned_docs/version-0.45/develop/advanced-concepts/{store.md => 04-store.md} (91%) rename versioned_docs/version-0.45/develop/advanced-concepts/{encoding.md => 05-encoding.md} (96%) rename versioned_docs/version-0.45/develop/advanced-concepts/{cli.md => 06-cli.md} (83%) rename versioned_docs/version-0.45/develop/advanced-concepts/{events.md => 07-events.md} (89%) rename versioned_docs/version-0.45/develop/advanced-concepts/{grpc_rest.md => 08-grpc_rest.md} (92%) rename versioned_docs/version-0.45/develop/advanced-concepts/{ocap.md => 09-ocap.md} (96%) rename versioned_docs/version-0.45/develop/advanced-concepts/{telemetry.md => 10-telemetry.md} (99%) rename versioned_docs/version-0.45/develop/advanced-concepts/{runtx_middleware.md => 11-runtx_middleware.md} (99%) rename versioned_docs/version-0.45/develop/advanced-concepts/{simulation.md => 12-simulation.md} (99%) rename versioned_docs/version-0.45/develop/advanced-concepts/{upgrade.md => 13-upgrade.md} (97%) delete mode 100644 versioned_docs/version-0.45/develop/advanced-concepts/README.md rename versioned_docs/version-0.45/develop/high-level-concepts/{app-anatomy.md => 00-overview-app.md} (70%) rename versioned_docs/version-0.45/develop/high-level-concepts/{tx-lifecycle.md => 01-tx-lifecycle.md} (81%) rename versioned_docs/version-0.45/develop/high-level-concepts/{query-lifecycle.md => 02-query-lifecycle.md} (69%) rename versioned_docs/version-0.45/develop/high-level-concepts/{accounts.md => 03-accounts.md} (96%) rename versioned_docs/version-0.45/develop/high-level-concepts/{gas-fees.md => 04-gas-fees.md} (70%) delete mode 100644 versioned_docs/version-0.45/develop/high-level-concepts/README.md create mode 100644 versioned_docs/version-0.45/develop/high-level-concepts/_category_.json delete mode 100644 versioned_docs/version-0.45/develop/intro/README.md create mode 100644 versioned_docs/version-0.45/integrate/_category_.json rename versioned_docs/version-0.45/integrate/building-modules/{intro.md => 00-intro.md} (77%) rename versioned_docs/version-0.45/integrate/building-modules/{module-manager.md => 01-module-manager.md} (63%) rename versioned_docs/version-0.45/integrate/building-modules/{messages-and-queries.md => 02-messages-and-queries.md} (72%) rename versioned_docs/version-0.45/integrate/building-modules/{msg-services.md => 03-msg-services.md} (71%) rename versioned_docs/version-0.45/integrate/building-modules/{query-services.md => 04-query-services.md} (65%) rename versioned_docs/version-0.45/integrate/building-modules/{beginblock-endblock.md => 05-beginblock-endblock.md} (63%) rename versioned_docs/version-0.45/integrate/building-modules/{keeper.md => 06-keeper.md} (70%) rename versioned_docs/version-0.45/integrate/building-modules/{invariants.md => 07-invariants.md} (82%) rename versioned_docs/version-0.45/integrate/building-modules/{genesis.md => 08-genesis.md} (62%) rename versioned_docs/version-0.45/integrate/building-modules/{module-interfaces.md => 09-module-interfaces.md} (84%) rename versioned_docs/version-0.45/integrate/building-modules/{structure.md => 10-structure.md} (98%) rename versioned_docs/version-0.45/integrate/building-modules/{errors.md => 11-errors.md} (99%) rename versioned_docs/version-0.45/integrate/building-modules/{upgrade.md => 12-upgrade.md} (97%) rename versioned_docs/version-0.45/integrate/building-modules/{simulator.md => 13-simulator.md} (99%) delete mode 100644 versioned_docs/version-0.45/integrate/building-modules/README.md create mode 100644 versioned_docs/version-0.45/integrate/building-modules/_category_.json delete mode 100644 versioned_docs/version-0.45/integrate/ibc/README.md create mode 100644 versioned_docs/version-0.45/integrate/ibc/_category_.json create mode 100644 versioned_docs/version-0.45/integrate/ibc/upgrades/_category_.json create mode 100644 versioned_docs/version-0.45/user/_category_.json rename versioned_docs/version-0.45/user/run-node/{keyring.md => 00-keyring.md} (96%) rename versioned_docs/version-0.45/user/run-node/{run-node.md => 01-run-node.md} (98%) rename versioned_docs/version-0.45/user/run-node/{interact-node.md => 02-interact-node.md} (93%) rename versioned_docs/version-0.45/user/run-node/{txs.md => 03-txs.md} (99%) rename versioned_docs/version-0.45/user/run-node/{rosetta.md => 04-rosetta.md} (100%) rename versioned_docs/version-0.45/user/run-node/{run-testnet.md => 05-run-testnet.md} (100%) create mode 100644 versioned_docs/version-0.45/user/run-node/_category_.json create mode 100644 versioned_docs/version-0.46/develop/_category_.json rename versioned_docs/version-0.46/develop/high-level-concepts/{app-anatomy.md => 00-overview-app.md} (66%) rename versioned_docs/version-0.46/develop/high-level-concepts/{tx-lifecycle.md => 01-tx-lifecycle.md} (79%) rename versioned_docs/version-0.46/develop/high-level-concepts/{query-lifecycle.md => 02-query-lifecycle.md} (67%) rename versioned_docs/version-0.46/develop/high-level-concepts/{accounts.md => 03-accounts.md} (96%) rename versioned_docs/version-0.46/develop/high-level-concepts/{gas-fees.md => 04-gas-fees.md} (69%) delete mode 100644 versioned_docs/version-0.46/develop/high-level-concepts/README.md create mode 100644 versioned_docs/version-0.46/develop/high-level-concepts/_category_.json rename versioned_docs/version-0.46/develop/intro/{overview.md => 00-what-is-sdk.md} (97%) rename versioned_docs/version-0.46/develop/intro/{why-app-specific.md => 01-why-app-specific.md} (99%) rename versioned_docs/version-0.46/develop/intro/{sdk-app-architecture.md => 02-sdk-app-architecture.md} (91%) rename versioned_docs/version-0.46/develop/intro/{sdk-design.md => 03-sdk-design.md} (82%) delete mode 100644 versioned_docs/version-0.46/develop/intro/README.md create mode 100644 versioned_docs/version-0.46/develop/intro/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/CosmWasm/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/architecture/_category_.json rename versioned_docs/{version-0.47/integrate/building-modules/01-intro.md => version-0.46/integrate/building-modules/00-intro.md} (83%) rename versioned_docs/version-0.46/integrate/building-modules/{module-manager.md => 01-module-manager.md} (63%) rename versioned_docs/version-0.46/integrate/building-modules/{messages-and-queries.md => 02-messages-and-queries.md} (72%) rename versioned_docs/version-0.46/integrate/building-modules/{msg-services.md => 03-msg-services.md} (72%) rename versioned_docs/version-0.46/integrate/building-modules/{query-services.md => 04-query-services.md} (64%) rename versioned_docs/version-0.46/integrate/building-modules/{beginblock-endblock.md => 05-beginblock-endblock.md} (62%) rename versioned_docs/version-0.46/integrate/building-modules/{keeper.md => 06-keeper.md} (70%) rename versioned_docs/version-0.46/integrate/building-modules/{invariants.md => 07-invariants.md} (81%) rename versioned_docs/version-0.46/integrate/building-modules/{genesis.md => 08-genesis.md} (60%) rename versioned_docs/version-0.46/integrate/building-modules/{module-interfaces.md => 09-module-interfaces.md} (84%) rename versioned_docs/version-0.46/integrate/building-modules/{structure.md => 11-structure.md} (98%) rename versioned_docs/version-0.46/integrate/building-modules/{errors.md => 12-errors.md} (99%) rename versioned_docs/version-0.46/integrate/building-modules/{upgrade.md => 13-upgrade.md} (90%) rename versioned_docs/version-0.46/integrate/building-modules/{simulator.md => 14-simulator.md} (98%) delete mode 100644 versioned_docs/version-0.46/integrate/building-modules/README.md create mode 100644 versioned_docs/version-0.46/integrate/building-modules/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/ibc/_category_.json rename versioned_docs/version-0.46/integrate/migrations/{pre-upgrade.md => 00-pre-upgrade.md} (100%) delete mode 100644 versioned_docs/version-0.46/integrate/migrations/README.md create mode 100644 versioned_docs/version-0.46/integrate/migrations/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/auth/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/authz/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/bank/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/capability/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/crisis/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/distribution/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/evidence/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/feegrant/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/gov/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/mint/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/params/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/slashing/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/staking/_category_.json create mode 100644 versioned_docs/version-0.46/integrate/modules/upgrade/_category_.json create mode 100644 versioned_docs/version-0.46/user/_category_.json rename versioned_docs/version-0.46/user/run-node/{keyring.md => 00-keyring.md} (96%) rename versioned_docs/version-0.46/user/run-node/{run-node.md => 01-run-node.md} (95%) rename versioned_docs/version-0.46/user/run-node/{interact-node.md => 02-interact-node.md} (93%) rename versioned_docs/version-0.46/user/run-node/{txs.md => 03-txs.md} (99%) rename versioned_docs/version-0.46/user/run-node/{rosetta.md => 04-rosetta.md} (99%) rename versioned_docs/version-0.46/user/run-node/{run-testnet.md => 05-run-testnet.md} (99%) delete mode 100644 versioned_docs/version-0.46/user/run-node/README.md create mode 100644 versioned_docs/version-0.46/user/run-node/_category_.json create mode 100644 versioned_docs/version-0.47/develop/_category_.json create mode 100644 versioned_docs/version-0.47/develop/advanced-concepts/05-interblock-cache.md rename versioned_docs/version-0.47/develop/advanced-concepts/{05-encoding.md => 06-encoding.md} (80%) rename versioned_docs/version-0.47/develop/advanced-concepts/{06-grpc_rest.md => 09-grpc_rest.md} (86%) rename versioned_docs/version-0.47/develop/advanced-concepts/{09-telemetry.md => 11-telemetry.md} (100%) rename versioned_docs/version-0.47/develop/advanced-concepts/{11-runtx_middleware.md => 12-runtx_middleware.md} (86%) rename versioned_docs/version-0.47/develop/advanced-concepts/{12-simulation.md => 13-simulation.md} (98%) rename versioned_docs/version-0.47/develop/advanced-concepts/{13-proto-docs.md => 14-proto-docs.md} (100%) rename versioned_docs/version-0.47/develop/advanced-concepts/{14-tips.md => 15-tips.md} (99%) rename versioned_docs/version-0.47/develop/advanced-concepts/{15-upgrade.md => 16-upgrade.md} (96%) create mode 100644 versioned_docs/version-0.47/develop/advanced-concepts/17-config.md create mode 100644 versioned_docs/version-0.47/develop/glossary.md rename versioned_docs/version-0.47/develop/high-level-concepts/{00-app-anatomy.md => 00-overview-app.md} (62%) create mode 100644 versioned_docs/version-0.47/integrate/_category_.json create mode 100644 versioned_docs/version-0.47/integrate/architecture/adr-054-semver-compatible-modules.md create mode 100644 versioned_docs/version-0.47/integrate/architecture/adr-062-collections-state-layer.md create mode 100644 versioned_docs/version-0.47/integrate/architecture/adr-063-core-module-api.md create mode 100644 versioned_docs/version-0.47/integrate/architecture/adr-064-abci-2.0.md create mode 100644 versioned_docs/version-0.47/integrate/architecture/adr-065-store-v2.md rename versioned_docs/{version-0.46/integrate/building-modules/intro.md => version-0.47/integrate/building-modules/00-intro.md} (73%) create mode 100644 versioned_docs/version-0.47/integrate/building-modules/transaction_flow.svg create mode 100644 versioned_docs/version-0.47/integrate/libraries/01-depinject.md create mode 100644 versioned_docs/version-0.47/integrate/libraries/02-collections.md create mode 100644 versioned_docs/version-0.47/integrate/libraries/03-orm.md create mode 100644 versioned_docs/version-0.47/integrate/libraries/04-packages.md create mode 100644 versioned_docs/version-0.47/integrate/libraries/_category_.json create mode 100644 versioned_docs/version-0.47/integrate/migrations/02-upgrading.md rename versioned_docs/{version-0.46 => version-0.47}/integrate/modules/README.md (90%) create mode 100644 versioned_docs/version-0.47/integrate/modules/auth/1-vesting.md create mode 100644 versioned_docs/version-0.47/integrate/modules/auth/2-tx.md create mode 100644 versioned_docs/version-0.47/integrate/modules/auth/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/authz/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/bank/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/circuit/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/consensus/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/crisis/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/distribution/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/evidence/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/feegrant/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/genutil/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/gov/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/group/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/mint/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/nft/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/params/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/slashing/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/staking/README.md create mode 100644 versioned_docs/version-0.47/integrate/modules/upgrade/README.md create mode 100644 versioned_docs/version-0.47/integrate/rfc/PROCESS.md create mode 100644 versioned_docs/version-0.47/integrate/rfc/README.md create mode 100644 versioned_docs/version-0.47/integrate/rfc/_category_.json create mode 100644 versioned_docs/version-0.47/integrate/rfc/rfc-001-tx-validation.md create mode 100644 versioned_docs/version-0.47/integrate/rfc/rfc-template.md delete mode 100644 versioned_docs/version-0.47/integrate/spec/README.md rename versioned_docs/version-0.47/integrate/spec/{SPEC-SPEC.md => SPEC_MODULE.md} (98%) create mode 100644 versioned_docs/version-0.47/integrate/spec/SPEC_STANDARD.md delete mode 100644 versioned_docs/version-0.47/integrate/spec/_ics/README.md delete mode 100644 versioned_docs/version-0.47/integrate/spec/circuit-breaker/README.md create mode 100644 versioned_docs/version-0.47/integrate/spec/ics/README.md rename versioned_docs/version-0.47/integrate/spec/{_ics => ics}/ics-030-signed-messages.md (99%) delete mode 100644 versioned_docs/version-0.47/integrate/spec/reserve-pool/README.md delete mode 100644 versioned_docs/version-0.47/integrate/spec/store/README.md create mode 100644 versioned_docs/version-0.47/integrate/tooling/01-cosmovisor.md create mode 100644 versioned_docs/version-0.47/integrate/tooling/02-confix.md rename versioned_docs/version-0.47/integrate/{building-modules/10-autocli.md => tooling/03-autocli.md} (97%) create mode 100644 versioned_docs/version-0.47/integrate/tooling/04-hubl.md create mode 100644 versioned_docs/version-0.47/integrate/tooling/05-depinject.md delete mode 100644 versioned_docs/version-0.47/integrate/tooling/README.md create mode 100644 versioned_docs/version-0.47/user/run-node/04-rosetta.md rename versioned_docs/version-0.47/{user/run-node => validate}/05-run-testnet.md (92%) diff --git a/docs/develop/advanced-concepts/07-cli.md b/docs/develop/advanced-concepts/07-cli.md index 89533c1c0..e7bf0b428 100644 --- a/docs/develop/advanced-concepts/07-cli.md +++ b/docs/develop/advanced-concepts/07-cli.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Command-Line Interface :::note Synopsis -This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../high-level-concepts/00-overview-app.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../../integrate/building-modules/01-intro.md) can be found [here](../../integrate/building-modules/09-module-interfaces.md#cli). +This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../high-level-concepts/00-overview-app.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../../integrate/building-modules/00-intro.md) can be found [here](../../integrate/building-modules/09-module-interfaces.md#cli). ::: ## Command-Line Interface diff --git a/docs/develop/high-level-concepts/00-overview-app.md b/docs/develop/high-level-concepts/00-overview-app.md index bb3cb4079..96716868e 100644 --- a/docs/develop/high-level-concepts/00-overview-app.md +++ b/docs/develop/high-level-concepts/00-overview-app.md @@ -148,7 +148,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L731-L738 ## Modules -[Modules](../../integrate/building-modules/01-intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed by [`baseapp`](../advanced-concepts/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). +[Modules](../../integrate/building-modules/00-intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed by [`baseapp`](../advanced-concepts/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). ### Application Module Interface diff --git a/docs/integrate/architecture/adr-038-state-listening.md b/docs/integrate/architecture/adr-038-state-listening.md index 37d856cc4..2b6a220b4 100644 --- a/docs/integrate/architecture/adr-038-state-listening.md +++ b/docs/integrate/architecture/adr-038-state-listening.md @@ -20,7 +20,7 @@ This ADR defines a set of changes to enable listening to state changes of indivi ## Context -Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/02-messages-and-queries.md#queries) which proceed either through Tendermint and the ABCI, or through the gRPC server. In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. diff --git a/docs/integrate/architecture/adr-040-storage-and-smt-state-commitments.md b/docs/integrate/architecture/adr-040-storage-and-smt-state-commitments.md index f60e3adcf..b089bfb1a 100644 --- a/docs/integrate/architecture/adr-040-storage-and-smt-state-commitments.md +++ b/docs/integrate/architecture/adr-040-storage-and-smt-state-commitments.md @@ -23,7 +23,7 @@ In the current design, IAVL is used for both data storage and as a Merkle Tree f * Each edge traversal requires a DB query. * Creating snapshots is [expensive](https://github.com/cosmos/cosmos-sdk/issues/7215#issuecomment-684804950). It takes about 30 seconds to export less than 100 MB of state (as of March 2020). * Updates in IAVL may trigger tree reorganization and possible O(log(n)) hashes re-computation, which can become a CPU bottleneck. -* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/node.md +* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/03-node.md ). Moreover, the IAVL project lacks support and a maintainer and we already see better and well-established alternatives. Instead of optimizing the IAVL, we are looking into other solutions for both storage and state commitments. diff --git a/docs/integrate/building-modules/01-intro.md b/docs/integrate/building-modules/00-intro.md similarity index 100% rename from docs/integrate/building-modules/01-intro.md rename to docs/integrate/building-modules/00-intro.md diff --git a/docs/integrate/building-modules/01-module-manager.md b/docs/integrate/building-modules/01-module-manager.md index 01e8dd727..0993a5999 100644 --- a/docs/integrate/building-modules/01-module-manager.md +++ b/docs/integrate/building-modules/01-module-manager.md @@ -12,7 +12,7 @@ Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-m ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: diff --git a/docs/integrate/building-modules/02-messages-and-queries.md b/docs/integrate/building-modules/02-messages-and-queries.md index 9d6956515..f5df41a98 100644 --- a/docs/integrate/building-modules/02-messages-and-queries.md +++ b/docs/integrate/building-modules/02-messages-and-queries.md @@ -12,7 +12,7 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: diff --git a/docs/integrate/building-modules/06-keeper.md b/docs/integrate/building-modules/06-keeper.md index e97e25e10..39305136f 100644 --- a/docs/integrate/building-modules/06-keeper.md +++ b/docs/integrate/building-modules/06-keeper.md @@ -12,7 +12,7 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: diff --git a/docs/integrate/building-modules/09-module-interfaces.md b/docs/integrate/building-modules/09-module-interfaces.md index 03cb750bd..d706df9b2 100644 --- a/docs/integrate/building-modules/09-module-interfaces.md +++ b/docs/integrate/building-modules/09-module-interfaces.md @@ -12,7 +12,7 @@ This document details how to build CLI and REST interfaces for a module. Example ### Pre-requisite Readings -* [Building Modules Intro](01-intro.md) +* [Building Modules Intro](00-intro.md) ::: diff --git a/docs/integrate/spec/addresses/bech32.md b/docs/integrate/spec/addresses/bech32.md index 2c15bac68..f996f9016 100644 --- a/docs/integrate/spec/addresses/bech32.md +++ b/docs/integrate/spec/addresses/bech32.md @@ -18,4 +18,4 @@ While all user facing interfaces to Cosmos software should exposed Bech32 interf To covert between other binary representation of addresses and keys, it is important to first apply the Amino encoding process before Bech32 encoding. -A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/cometbft/cometbft/blob/main/spec/blockchain/encoding.md) to the byte string payload before Bech32 encoding will sufficient for compatible representation. +A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/cometbft/cometbft/blob/main/spec/blockchain/05-encoding.md) to the byte string payload before Bech32 encoding will sufficient for compatible representation. diff --git a/docs/integrate/tooling/01-cosmovisor.md b/docs/integrate/tooling/01-cosmovisor.md index 6f6df095d..08e01f5a9 100644 --- a/docs/integrate/tooling/01-cosmovisor.md +++ b/docs/integrate/tooling/01-cosmovisor.md @@ -322,7 +322,7 @@ cosmovisor run start Update app to the latest version (e.g. v0.45). -Next, we can add a migration - which is defined using `x/upgrade` [upgrade plan](https://github.com/cosmos/cosmos-sdk/blob/main/docs/core/upgrade.md) (you may refer to a past version if you are using an older Cosmos SDK release). In a migration we can do any deterministic state change. +Next, we can add a migration - which is defined using `x/upgrade` [upgrade plan](https://github.com/cosmos/cosmos-sdk/blob/main/docs/advanced-concepts/13-upgrade.md) (you may refer to a past version if you are using an older Cosmos SDK release). In a migration we can do any deterministic state change. Build the new version `simd` binary: diff --git a/docs/integrate/tooling/03-autocli.md b/docs/integrate/tooling/03-autocli.md index e0804979a..5b50774c0 100644 --- a/docs/integrate/tooling/03-autocli.md +++ b/docs/integrate/tooling/03-autocli.md @@ -13,7 +13,7 @@ This document details how to build CLI and REST interfaces for a module. Example ## Pre-requisite Readings -* [Building Modules Intro](../building-modules/01-intro.md) +* [Building Modules Intro](../building-modules/00-intro.md) ::: diff --git a/docusaurus.config.js b/docusaurus.config.js index 4a8eb2c73..418c7722a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -73,7 +73,7 @@ const config = { label: "Develop", }, { - to: "/integrate/building-apps/app-go", + to: "/integrate/building-modules/intro", position: "left", label: "Integrate", }, diff --git a/versioned_docs/version-0.45/develop/_category_.json b/versioned_docs/version-0.45/develop/_category_.json new file mode 100644 index 000000000..f40637f4d --- /dev/null +++ b/versioned_docs/version-0.45/develop/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Develop", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/baseapp.md b/versioned_docs/version-0.45/develop/advanced-concepts/00-baseapp.md similarity index 82% rename from versioned_docs/version-0.45/develop/advanced-concepts/baseapp.md rename to versioned_docs/version-0.45/develop/advanced-concepts/00-baseapp.md index c3da524e3..2160150d7 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/baseapp.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/00-baseapp.md @@ -1,15 +1,11 @@ - - # BaseApp This document describes `BaseApp`, the abstraction that implements the core functionalities of an SDK application. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} -- [Lifecycle of an SDK transaction](../basics/tx-lifecycle.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/00-overview-app.md) {prereq} +- [Lifecycle of an SDK transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Introduction @@ -54,7 +50,7 @@ Let us go through the most important components. First, the important parameters that are initialized during the bootstrapping of the application: -- [`CommitMultiStore`](./store.md#commitmultistore): This is the main store of the application, +- [`CommitMultiStore`](./04-store.md#commitmultistore): This is the main store of the application, which holds the canonical state that is committed at the [end of each block](#commit). This store is **not** cached, meaning it is not used to update the application's volatile (un-committed) states. The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application @@ -73,8 +69,8 @@ First, the important parameters that are initialized during the bootstrapping of - [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment, and other pre-message execution checks when a transaction is received. It's executed during [`CheckTx/RecheckTx`](#checktx) and [`DeliverTx`](#delivertx). -- [`InitChainer`](../basics/app-anatomy.md#initchainer), - [`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): These are +- [`InitChainer`](../high-level-concepts/00-overview-app.md#initchainer), + [`BeginBlocker` and `EndBlocker`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblocker): These are the functions executed when the application receives the `InitChain`, `BeginBlock` and `EndBlock` ABCI messages from the underlying Tendermint engine. @@ -98,7 +94,7 @@ Finally, a few more important parameterd: `minGasPrices` (e.g. if `minGasPrices == 1uatom,1photon`, the `gas-price` of the transaction must be greater than `1uatom` OR `1photon`). - `appVersion`: Version of the application. It is set in the - [application's constructor function](../basics/app-anatomy.md#constructor-function). + [application's constructor function](../high-level-concepts/00-overview-app.md#constructor-function). ## Constructor @@ -191,17 +187,17 @@ When messages and queries are received by the application, they must be routed t ### `Msg` Service Router -[`sdk.Msg`s](#../building-modules/messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. +[`sdk.Msg`s](../../integrate/building-modules/02-messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. The [default `msgServiceRouter` included in `BaseApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go) is stateless. However, some applications may want to make use of more stateful routing mechanisms such as allowing governance to disable certain routes or point them to new modules for upgrade purposes. For this reason, the `sdk.Context` is also passed into each [route handler inside `msgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go#L31-L32). For a stateless router that doesn't want to make use of this, you can just ignore the `ctx`. -The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor). +The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/01-module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#app-constructor). ### gRPC Query Router -Similar to `sdk.Msg`s, [`queries`](../building-modules/messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint. +Similar to `sdk.Msg`s, [`queries`](../building-modules/02-messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/04-query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint. -Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor). +Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/01-module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#app-constructor). ## Main ABCI Messages @@ -226,23 +222,23 @@ Unconfirmed transactions are relayed to peers only if they pass `CheckTx`. `CheckTx()` can perform both _stateful_ and _stateless_ checks, but developers should strive to make the checks **lightweight** because gas fees are not charged for the resources (CPU, data load...) used during the `CheckTx`. -In the Cosmos SDK, after [decoding transactions](./encoding.md), `CheckTx()` is implemented +In the Cosmos SDK, after [decoding transactions](./05-encoding.md), `CheckTx()` is implemented to do the following checks: 1. Extract the `sdk.Msg`s from the transaction. 2. Perform _stateless_ checks by calling `ValidateBasic()` on each of the `sdk.Msg`s. This is done first, as _stateless_ checks are less computationally expensive than _stateful_ checks. If `ValidateBasic()` fail, `CheckTx` returns before running _stateful_ checks, which saves resources. -3. Perform non-module related _stateful_ checks on the [account](../basics/accounts.md). This step is mainly about checking +3. Perform non-module related _stateful_ checks on the [account](../high-level-concepts/03-accounts.md). This step is mainly about checking that the `sdk.Msg` signatures are valid, that enough fees are provided and that the sending account - has enough funds to pay for said fees. Note that no precise [`gas`](../basics/gas-fees.md) counting occurs here, - as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../basics/gas-fees.md#antehandler) will check that the `gas` provided + has enough funds to pay for said fees. Note that no precise [`gas`](../high-level-concepts/gas-fees.md) counting occurs here, + as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) will check that the `gas` provided with the transaction is superior to a minimum reference gas amount based on the raw transaction size, in order to avoid spam with transactions that provide 0 gas. `CheckTx` does **not** process `sdk.Msg`s - they only need to be processed when the canonical state need to be updated, which happens during `DeliverTx`. -Steps 2. and 3. are performed by the [`AnteHandler`](../basics/gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs) +Steps 2. and 3. are performed by the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs) function, which `CheckTx()` calls with the `runTxModeCheck` mode. During each step of `CheckTx()`, a special [volatile state](#volatile-states) called `checkState` is updated. This state is used to keep track of the temporary changes triggered by the `CheckTx()` calls of each transaction without modifying @@ -264,7 +260,7 @@ The response contains: - `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction. - `GasUsed (int64)`: Amount of gas consumed by transaction. During `CheckTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction. Next is an example: +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/ante/basic.go#L104-L105 -- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./events.md) for more. +- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./07-events.md) for more. - `Codespace (string)`: Namespace for the Code. #### RecheckTx @@ -285,7 +281,7 @@ Before the first transaction of a given block is processed, a [volatile state](# `DeliverTx` performs the **exact same steps as `CheckTx`**, with a little caveat at step 3 and the addition of a fifth step: 1. The `AnteHandler` does **not** check that the transaction's `gas-prices` is sufficient. That is because the `min-gas-prices` value `gas-prices` is checked against is local to the node, and therefore what is enough for one full-node might not be for another. This means that the proposer can potentially include transactions for free, although they are not incentivised to do so, as they earn a bonus on the total fee of the block they propose. -2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. +2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: @@ -301,7 +297,7 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0 - `Info (string):` Additional information. May be non-deterministic. - `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction. - `GasUsed (int64)`: Amount of gas consumed by transaction. During `DeliverTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction, and by adding gas each time a read/write to the store occurs. -- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./events.md) for more. +- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./07-events.md) for more. - `Codespace (string)`: Namespace for the Code. ## RunTx, AnteHandler and RunMsgs @@ -310,7 +306,7 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0 `RunTx` is called from `CheckTx`/`DeliverTx` to handle the transaction, with `runTxModeCheck` or `runTxModeDeliver` as parameter to differentiate between the two modes of execution. Note that when `RunTx` receives a transaction, it has already been decoded. -The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../basics/gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. +The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../high-level-concepts/gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. After that, `RunTx()` calls `ValidateBasic()` on each `sdk.Msg`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `sdk.Msg` fails to pass `ValidateBasic()`, `RunTx()` returns with an error. @@ -318,7 +314,7 @@ Then, the [`anteHandler`](#antehandler) of the application is run (if it exists) +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/baseapp.go#L623-L630 -This allows `RunTx` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](./ocap.md) of the Cosmos SDK. +This allows `RunTx` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](./09-ocap.md) of the Cosmos SDK. Finally, the [`RunMsgs()`](#runmsgs) function is called to process the `sdk.Msg`s in the `Tx`. In preparation of this step, just like with the `anteHandler`, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are branched using the `cacheTxContext()` function. @@ -330,19 +326,19 @@ The `AnteHandler` is a special handler that implements the `AnteHandler` interfa The `AnteHandler` is theoretically optional, but still a very important component of public blockchain networks. It serves 3 primary purposes: -- Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and [`sequence`](./transactions.md#transaction-generation) checking. +- Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and [`sequence`](./01-transactions.md#transaction-generation) checking. - Perform preliminary _stateful_ validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees. - Play a role in the incentivisation of stakeholders via the collection of transaction fees. -`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/ante/ante.go). +`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../high-level-concepts/00-overview-app.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/ante/ante.go). -Click [here](../basics/gas-fees.md#antehandler) for more on the `anteHandler`. +Click [here](../high-level-concepts/gas-fees.md#antehandler) for more on the `anteHandler`. ### RunMsgs `RunMsgs` is called from `RunTx` with `runTxModeCheck` as parameter to check the existence of a route for each message the transaction, and with `runTxModeDeliver` to actually process the `sdk.Msg`s. -First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/msg-services.md) RPC is executed, before `RunMsgs` returns. +First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/03-msg-services.md) RPC is executed, before `RunMsgs` returns. ## Other ABCI Messages @@ -352,9 +348,9 @@ The [`InitChain` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.htm - [Consensus Parameters](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters) via `setConsensusParams`. - [`checkState` and `deliverState`](#volatile-states) via `setCheckState` and `setDeliverState`. -- The [block gas meter](../basics/gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. +- The [block gas meter](../high-level-concepts/gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. -Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../basics/app-anatomy.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules. +Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../high-level-concepts/00-overview-app.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/08-genesis.md#initgenesis) function of each of the application's modules. ### BeginBlock @@ -362,14 +358,14 @@ The [`BeginBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.h - Initialize [`deliverState`](#volatile-states) with the latest header using the `req abci.RequestBeginBlock` passed as parameter via the `setDeliverState` function. +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L387-L397 - This function also resets the [main gas meter](../basics/gas-fees.md#main-gas-meter). -- Initialize the [block gas meter](../basics/gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. -- Run the application's [`beginBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. -- Set the [`VoteInfos`](https://tendermint.com/docs/app-dev/abci-spec.html#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./context.md) so that it can be used during `DeliverTx` and `EndBlock`. + This function also resets the [main gas meter](../high-level-concepts/gas-fees.md#main-gas-meter). +- Initialize the [block gas meter](../high-level-concepts/gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. +- Run the application's [`beginBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. +- Set the [`VoteInfos`](https://tendermint.com/docs/app-dev/abci-spec.html#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./02-context.md) so that it can be used during `DeliverTx` and `EndBlock`. ### EndBlock -The [`EndBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. +The [`EndBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. ### Commit @@ -385,15 +381,15 @@ The [`Info` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#inf ### Query -The [`Query` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#query) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../building-modules/query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://tendermint.com/docs/app-dev/abci-spec.html#query). +The [`Query` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#query) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../building-modules/04-query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://tendermint.com/docs/app-dev/abci-spec.html#query). Each Tendermint `query` comes with a `path`, which is a `string` which denotes what to query. If the `path` matches a gRPC fully-qualified service method, then `BaseApp` will defer the query to the `grpcQueryRouter` and let it handle it like explained [above](#grpc-query-router). Otherwise, the `path` represents a query that is not (yet) handled by the gRPC router. `BaseApp` splits the `path` string with the `/` delimiter. By convention, the first element of the splitted string (`splitted[0]`) contains the category of `query` (`app`, `p2p`, `store` or `custom` ). The `BaseApp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving these 4 main categories of queries: - Application-related queries like querying the application's version, which are served via the `handleQueryApp` method. - Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queries are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers. - P2P queries, which are served via the `handleQueryP2P` method. These queries return either `app.addrPeerFilter` or `app.ipPeerFilter` that contain the list of peers filtered by address or IP respectively. These lists are first initialized via `options` in `BaseApp`'s [constructor](#constructor). -- Custom queries, which encompass legacy queries (before the introduction of gRPC queries), are served via the `handleQueryCustom` method. The `handleQueryCustom` branches the multistore before using the `queryRoute` obtained from `app.queryRouter` to map the query to the appropriate module's [legacy `querier`](../building-modules/query-services.md#legacy-queriers). +- Custom queries, which encompass legacy queries (before the introduction of gRPC queries), are served via the `handleQueryCustom` method. The `handleQueryCustom` branches the multistore before using the `queryRoute` obtained from `app.queryRouter` to map the query to the appropriate module's [legacy `querier`](../building-modules/04-query-services.md#legacy-queriers). ## Next {hide} -Learn more about [transactions](./transactions.md) {hide} +Learn more about [transactions](./01-transactions.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/transactions.md b/versioned_docs/version-0.45/develop/advanced-concepts/01-transactions.md similarity index 75% rename from versioned_docs/version-0.45/develop/advanced-concepts/transactions.md rename to versioned_docs/version-0.45/develop/advanced-concepts/01-transactions.md index 710df881a..8791e945b 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/transactions.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/01-transactions.md @@ -1,20 +1,16 @@ - - # Transactions `Transactions` are objects created by end-users to trigger state changes in the application. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK Application](../high-level-concepts/overview-app.md) {prereq} ## Transactions -Transactions are comprised of metadata held in [contexts](./context.md) and [`sdk.Msg`s](../building-modules/messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../building-modules/msg-services.md). +Transactions are comprised of metadata held in [contexts](./02-context.md) and [`sdk.Msg`s](../building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../integrate/building-modules/03-msg-services.md). -When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../basics/tx-lifecycle.md). +When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../high-level-concepts/01-tx-lifecycle.md). ## Type Definition @@ -25,7 +21,7 @@ Transaction objects are SDK types that implement the `Tx` interface It contains the following methods: - **GetMsgs:** unwraps the transaction and returns a list of contained `sdk.Msg`s - one transaction may have one or multiple messages, which are defined by module developers. -- **ValidateBasic:** lightweight, [_stateless_](../basics/tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./baseapp.md#checktx) and [`DeliverTx`](./baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth) module's `StdTx` `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from `sdk.Msg` [`ValidateBasic`](../basics/tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. +- **ValidateBasic:** lightweight, [_stateless_](../high-level-concepts/01-tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./00-baseapp.md#checktx) and [`DeliverTx`](./00-baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth) module's `StdTx` `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from `sdk.Msg` [`ValidateBasic`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./00-baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. As a developer, you should rarely manipulate `Tx` directly, as `Tx` is really an intermediate type used for transaction generation. Instead, developers should prefer the `TxBuilder` interface, which you can learn more about [below](#transaction-generation). @@ -77,12 +73,12 @@ The next paragraphs will describe each of these components, in this order. Module `sdk.Msg`s are not to be confused with [ABCI Messages](https://tendermint.com/docs/spec/abci/abci.html#messages) which define interactions between the Tendermint and application layers. ::: -**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../building-modules/msg-services.md), and also implement the corresponding `MsgServer`. +**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../building-modules/03-msg-services.md), and also implement the corresponding `MsgServer`. -Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../building-modules/msg-services.md) RPC, defined inside each module's `tx.proto` file. An SKD app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. +Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../building-modules/03-msg-services.md) RPC, defined inside each module's `tx.proto` file. An SKD app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. This design puts more responsibility on module developers, allowing application developers to reuse common functionalities without having to implement state transition logic repetitively. -To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../building-modules/msg-services.md). +To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../building-modules/03-msg-services.md). While messages contain the information for state transition logic, a transaction's other metadata and relevant information are stored in the `TxBuilder` and `Context`. @@ -126,9 +122,9 @@ Once the transaction bytes are generated, there are currently three ways of broa #### CLI -Application developers create entrypoints to the application by creating a [command-line interface](../core/cli.md), [gRPC and/or REST interface](../core/grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. +Application developers create entrypoints to the application by creating a [command-line interface](../06-cli.md), [gRPC and/or REST interface](../08-grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. -For the [command-line interface](../building-modules/module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../run-node/interact-node.md) section. An example transaction made using CLI looks like: +For the [command-line interface](../building-modules/09-module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../run-node/interact-node.md) section. An example transaction made using CLI looks like: ```bash simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake @@ -142,13 +138,13 @@ simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake The `Tx` service exposes a handful of utility functions, such as simulating a transaction or querying a transaction, and also one method to broadcast transactions. -Examples of broadcasting and simulating a transaction are shown [here](../run-node/txs.md#programmatically-with-go). +Examples of broadcasting and simulating a transaction are shown [here](../../user/run-node/txs.md#programmatically-with-go). #### REST Each gRPC method has its corresponding REST endpoint, generated using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). Therefore, instead of using gRPC, you can also use HTTP to broadcast the same transaction, on the `POST /cosmos/tx/v1beta1/txs` endpoint. -An example can be seen [here](../run-node/txs.md#using-rest) +An example can be seen [here](../../user/run-node/txs.md#using-rest) #### Tendermint RPC @@ -156,4 +152,4 @@ The three methods presented above are actually higher abstractions over the Tend ## Next {hide} -Learn about the [context](./context.md) {hide} +Learn about the [context](./02-context.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/context.md b/versioned_docs/version-0.45/develop/advanced-concepts/02-context.md similarity index 68% rename from versioned_docs/version-0.45/develop/advanced-concepts/context.md rename to versioned_docs/version-0.45/develop/advanced-concepts/02-context.md index 1fc74bd8a..7fcf5202f 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/context.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/02-context.md @@ -1,34 +1,30 @@ - - # Context The `context` is a data structure intended to be passed from function to function that carries information about the current state of the application. It provides an access to a branched storage (a safe branch of the entire state) as well as useful objects and information like `gasMeter`, `block height`, `consensus parameters` and more. {synopsis} ## Pre-requisites Readings -- [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq} -- [Lifecycle of a Transaction](../basics/tx-lifecycle.md) {prereq} +- [Anatomy of an SDK Application](../high-level-concepts/overview-app.md) {prereq} +- [Lifecycle of a Transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Context Definition -The SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://golang.org/pkg/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./store.md#base-layer-kvstores) in the [`multistore`](./store.md#multistore) and retrieve transactional context such as the block header and gas meter. +The SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://golang.org/pkg/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./04-store.md#base-layer-kvstores) in the [`multistore`](./04-store.md#multistore) and retrieve transactional context such as the block header and gas meter. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/context.go#L16-L39 - **Context:** The base type is a Go [Context](https://golang.org/pkg/context), which is explained further in the [Go Context Package](#go-context-package) section below. -- **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](./store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](./store.md#base-layer-kvstores) using their unique `StoreKey`. +- **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](./04-store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](./04-store.md#base-layer-kvstores) using their unique `StoreKey`. - **ABCI Header:** The [header](https://tendermint.com/docs/spec/abci/abci.html#header) is an ABCI type. It carries important information about the state of the blockchain, such as block height and proposer of the current block. - **Chain ID:** The unique identification number of the blockchain a block pertains to. -- **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the SDK and consensus engine (e.g. Tendermint) throughout its [lifecycle](../basics/tx-lifecycle.md), some of which to not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./encoding.md) such as [Amino](./encoding.md). +- **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the SDK and consensus engine (e.g. Tendermint) throughout its [lifecycle](../high-level-concepts/01-tx-lifecycle.md), some of which to not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./05-encoding.md) such as [Amino](./05-encoding.md). - **Logger:** A `logger` from the Tendermint libraries. Learn more about logs [here](https://tendermint.com/docs/tendermint-core/how-to-read-logs.html#how-to-read-logs). Modules call this method to create their own unique module-specific logger. - **VoteInfo:** A list of the ABCI type [`VoteInfo`](https://tendermint.com/docs/spec/abci/abci.html#voteinfo), which includes the name of a validator and a boolean indicating whether they have signed the block. -- **Gas Meters:** Specifically, a [`gasMeter`](../basics/gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../basics/gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../basics/gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. +- **Gas Meters:** Specifically, a [`gasMeter`](../high-level-concepts/gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../high-level-concepts/gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../high-level-concepts/gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. - **CheckTx Mode:** A boolean value indicating whether a transaction should be processed in `CheckTx` or `DeliverTx` mode. -- **Min Gas Price:** The minimum [gas](../basics/gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. +- **Min Gas Price:** The minimum [gas](../high-level-concepts/gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. - **Consensus Params:** The ABCI type [Consensus Parameters](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters), which specify certain limits for the blockchain, such as maximum gas for a block. -- **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](./events.md). Modules may define module specific +- **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](./07-events.md). Modules may define module specific `Events` by defining various `Types` and `Attributes` or use the common definitions found in `types/`. Clients can subscribe or query for these `Events`. These `Events` are collected throughout `DeliverTx`, `BeginBlock`, and `EndBlock` and are returned to Tendermint for indexing. For example: ```go @@ -65,15 +61,15 @@ goes wrong. The pattern of usage for a Context is as follows: 1. A process receives a Context `ctx` from its parent process, which provides information needed to perform the process. -2. The `ctx.ms` is a **branched store**, i.e. a branch of the [multistore](./store.md#multistore) is made so that the process can make changes to the state as it executes, without changing the original`ctx.ms`. This is useful to protect the underlying multistore in case the changes need to be reverted at some point in the execution. +2. The `ctx.ms` is a **branched store**, i.e. a branch of the [multistore](./04-store.md#multistore) is made so that the process can make changes to the state as it executes, without changing the original`ctx.ms`. This is useful to protect the underlying multistore in case the changes need to be reverted at some point in the execution. 3. The process may read and write from `ctx` as it is executing. It may call a subprocess and pass `ctx` to it as needed. 4. When a subprocess returns, it checks if the result is a success or failure. If a failure, nothing needs to be done - the branch `ctx` is simply discarded. If successful, the changes made to the `CacheMultiStore` can be committed to the original `ctx.ms` via `Write()`. -For example, here is a snippet from the [`runTx`](./baseapp.md#runtx-and-runmsgs) function in -[`baseapp`](./baseapp.md): +For example, here is a snippet from the [`runTx`](./00-baseapp.md#runtx-and-runmsgs) function in +[`baseapp`](./00-baseapp.md): ```go runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes) @@ -94,11 +90,11 @@ Here is the process: 1. Prior to calling `runMsgs` on the message(s) in the transaction, it uses `app.cacheTxContext()` to branch and cache the context and multistore. 2. `runMsgCtx` - the context with branched store, is used in `runMsgs` to return a result. -3. If the process is running in [`checkTxMode`](./baseapp.md#checktx), there is no need to write the +3. If the process is running in [`checkTxMode`](./00-baseapp.md#checktx), there is no need to write the changes - the result is returned immediately. -4. If the process is running in [`deliverTxMode`](./baseapp.md#delivertx) and the result indicates +4. If the process is running in [`deliverTxMode`](./00-baseapp.md#delivertx) and the result indicates a successful run over all the messages, the branched multistore is written back to the original. ## Next {hide} -Learn about the [node client](./node.md) {hide} +Learn about the [node client](./03-node.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/node.md b/versioned_docs/version-0.45/develop/advanced-concepts/03-node.md similarity index 82% rename from versioned_docs/version-0.45/develop/advanced-concepts/node.md rename to versioned_docs/version-0.45/develop/advanced-concepts/03-node.md index 132b6a8a8..1af7d0ea0 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/node.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/03-node.md @@ -1,14 +1,10 @@ - - -# Node Client (Daemon) +=# Node Client (Daemon) The main endpoint of an SDK application is the daemon client, otherwise known as the full-node client. The full-node runs the state-machine, starting from a genesis file. It connects to peers running the same client in order to receive and relay transactions, block proposals and signatures. The full-node is constituted of the application, defined with the Cosmos SDK, and of a consensus engine connected to the application via the ABCI. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/overview-app.md) {prereq} ## `main` function @@ -16,8 +12,8 @@ The full-node client of any SDK application is built by running a `main` functio In general, developers will implement the `main.go` function with the following structure: -- First, an [`appCodec`](./encoding.md) is instantiated for the application. -- Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../basics/accounts.md#addresses). +- First, an [`appCodec`](./05-encoding.md) is instantiated for the application. +- Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../high-level-concepts/03-accounts.md#addresses). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/config.go#L13-L24 - Using [cobra](https://github.com/spf13/cobra), the root command of the full-node client is created. After that, all the custom commands of the application are added using the `AddCommand()` method of `rootCmd`. - Add default server commands to `rootCmd` using the `server.AddCommands()` method. These commands are separated from the ones added above since they are standard and defined at SDK level. They should be shared by all SDK-based applications. They include the most important command: the [`start` command](#start-command). @@ -51,7 +47,7 @@ With the `db`, the `start` command creates a new instance of the application usi Note that an `appCreator` is a function that fulfills the `AppCreator` signature: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 -In practice, the [constructor of the application](../basics/app-anatomy.md#constructor-function) is passed as the `appCreator`. +In practice, the [constructor of the application](../high-level-concepts/overview-app.md#constructor-function) is passed as the `appCreator`. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/simd/cmd/root.go#L170-L215 @@ -59,7 +55,7 @@ Then, the instance of `app` is used to instanciate a new Tendermint node: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L235-L244 -The Tendermint node can be created with `app` because the latter satisfies the [`abci.Application` interface](https://github.com/tendermint/tendermint/blob/v0.34.0/abci/types/application.go#L7-L32) (given that `app` extends [`baseapp`](./baseapp.md)). As part of the `NewNode` method, Tendermint makes sure that the height of the application (i.e. number of blocks since genesis) is equal to the height of the Tendermint node. The difference between these two heights should always be negative or null. If it is strictly negative, `NewNode` will replay blocks until the height of the application reaches the height of the Tendermint node. Finally, if the height of the application is `0`, the Tendermint node will call [`InitChain`](./baseapp.md#initchain) on the application to initialize the state from the genesis file. +The Tendermint node can be created with `app` because the latter satisfies the [`abci.Application` interface](https://github.com/tendermint/tendermint/blob/v0.34.0/abci/types/application.go#L7-L32) (given that `app` extends [`baseapp`](./00-baseapp.md)). As part of the `NewNode` method, Tendermint makes sure that the height of the application (i.e. number of blocks since genesis) is equal to the height of the Tendermint node. The difference between these two heights should always be negative or null. If it is strictly negative, `NewNode` will replay blocks until the height of the application reaches the height of the Tendermint node. Finally, if the height of the application is `0`, the Tendermint node will call [`InitChain`](./00-baseapp.md#initchain) on the application to initialize the state from the genesis file. Once the Tendermint node is instanciated and in sync with the application, the node can be started: @@ -73,4 +69,4 @@ To discover how to concretely run a node and interact with it, please refer to o ## Next {hide} -Learn about the [store](./store.md) {hide} +Learn about the [store](./04-store.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/store.md b/versioned_docs/version-0.45/develop/advanced-concepts/04-store.md similarity index 91% rename from versioned_docs/version-0.45/develop/advanced-concepts/store.md rename to versioned_docs/version-0.45/develop/advanced-concepts/04-store.md index 1dbe05536..b490bd35b 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/store.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/04-store.md @@ -1,18 +1,14 @@ - - # Store A store is a data structure that holds the state of the application. {synopsis} ### Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/overview-app.md) {prereq} ## Introduction to SDK Stores -The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store. +The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/06-keeper.md) of the module that declared the store. ``` +-----------------------------------------------------+ @@ -64,7 +60,7 @@ The `GetStoreType` is a simple method that returns the type of store, whereas a +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/store.go#L240-L264 -Branching and cache is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A storage branch creates an isolated, ephemeral branch of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. Read more about it in [context](./context.md#Store-branching) +Branching and cache is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A storage branch creates an isolated, ephemeral branch of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. Read more about it in [context](./02-context.md#Store-branching) ### Commit Store @@ -76,7 +72,7 @@ The `Committer` is an interface that defines methods to persist changes to disk: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/store.go#L20-L27 -The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`. +The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./09-ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`. The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores. @@ -100,7 +96,7 @@ As for concrete implementation, the [`rootMulti.Store`] is the go-to implementat +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/rootmulti/store.go#L43-L61 -The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./baseapp.md). +The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./00-baseapp.md). ### CacheMultiStore @@ -116,9 +112,9 @@ Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](http A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer. -Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store. +Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/06-keeper.md) of the module that defines the store. -`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. +`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../high-level-concepts/overview-app.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/store.go#L189-L219 @@ -160,7 +156,7 @@ This type of store is useful to persist information that is only relevant per-bl +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/x/params/types/subspace.go#L20-L30 -Transient stores are typically accessed via the [`context`](./context.md) via the `TransientStore()` method: +Transient stores are typically accessed via the [`context`](./02-context.md) via the `TransientStore()` method: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/types/context.go#L232-L235 @@ -188,7 +184,7 @@ This is the type used whenever an IAVL Store needs to be branched to create an i ### `GasKv` Store -Cosmos SDK applications use [`gas`](../basics/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications. +Cosmos SDK applications use [`gas`](../high-level-concepts/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/gaskv/store.go#L13-L19 @@ -196,7 +192,7 @@ When methods of the parent `KVStore` are called, `GasKv.Store` automatically con +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/gas.go#L153-L162 -By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is done in the `KVStore()` method of the [`context`](./context.md): +By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is done in the `KVStore()` method of the [`context`](./02-context.md): +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/types/context.go#L227-L230 @@ -254,4 +250,4 @@ A `BasicKVStore` which is used to partially expose functions of an underlying st ## Next {hide} -Learn about [encoding](./encoding.md) {hide} +Learn about [encoding](./05-encoding.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/encoding.md b/versioned_docs/version-0.45/develop/advanced-concepts/05-encoding.md similarity index 96% rename from versioned_docs/version-0.45/develop/advanced-concepts/encoding.md rename to versioned_docs/version-0.45/develop/advanced-concepts/05-encoding.md index 084cffada..8f258b37f 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/encoding.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/05-encoding.md @@ -1,14 +1,10 @@ - - # Encoding While encoding in the SDK used to be mainly handled by `go-amino` codec, the SDK is moving towards using `gogoprotobuf` for both state and client-side encoding. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/overview-app.md) {prereq} ## Encoding @@ -83,7 +79,7 @@ In addition to [following official Protocol Buffer guidelines](https://developer ### Transaction Encoding Another important use of Protobuf is the encoding and decoding of -[transactions](./transactions.md). Transactions are defined by the application or +[transactions](./01-transactions.md). Transactions are defined by the application or the SDK but are then passed to the underlying consensus engine to be relayed to other peers. Since the underlying consensus engine is agnostic to the application, the consensus engine accepts only transactions in the form of raw bytes. @@ -103,7 +99,7 @@ See [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) for deta ### Interface Encoding and Usage of `Any` -The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../basics/accounts.md): +The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../high-level-concepts/03-accounts.md): ```proto message Profile { @@ -213,9 +209,9 @@ A real-life example of encoding the pubkey as `Any` inside the Validator struct Protobuf types can be defined to encode: - state -- [`Msg`s](../building-modules/messages-and-queries.md#messages) -- [Query services](../building-modules/query-services.md) -- [genesis](../building-modules/genesis.md) +- [`Msg`s](../building-modules/02-messages-and-queries.md#messages) +- [Query services](../building-modules/04-query-services.md) +- [genesis](../building-modules/08-genesis.md) **Naming and conventions** @@ -258,4 +254,4 @@ type UnpackInterfacesMessage interface { ## Next {hide} -Learn about [gRPC, REST and other endpoints](./grpc_rest.md) {hide} +Learn about [gRPC, REST and other endpoints](./08-grpc_rest.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/cli.md b/versioned_docs/version-0.45/develop/advanced-concepts/06-cli.md similarity index 83% rename from versioned_docs/version-0.45/develop/advanced-concepts/cli.md rename to versioned_docs/version-0.45/develop/advanced-concepts/06-cli.md index 36a225cb3..c1eda3484 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/cli.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/06-cli.md @@ -1,10 +1,6 @@ - - # Command-Line Interface -This document describes how commmand-line interface (CLI) works on a high-level, for an [**application**](../basics/app-anatomy.md). A separate document for implementing a CLI for an SDK [**module**](../building-modules/intro.md) can be found [here](../building-modules/module-interfaces.md#cli). {synopsis} +This document describes how commmand-line interface (CLI) works on a high-level, for an [**application**](../high-level-concepts/overview-app.md). A separate document for implementing a CLI for an SDK [**module**](../building-modules/intro.md) can be found [here](../building-modules/09-module-interfaces.md#cli). {synopsis} ## Command-Line Interface @@ -27,7 +23,7 @@ The first four strings specify the command: The next two strings are arguments: the `from_address` the user wishes to send from, the `to_address` of the recipient, and the `amount` they want to send. Finally, the last few strings of the command are optional flags to indicate how much the user is willing to pay in fees (calculated using the amount of gas used to execute the transaction and the gas prices provided by the user). -The CLI interacts with a [node](../core/node.md) to handle this command. The interface itself is defined in a `main.go` file. +The CLI interacts with a [node](../03-node.md) to handle this command. The interface itself is defined in a `main.go` file. ### Building the CLI @@ -35,7 +31,7 @@ The `main.go` file needs to have a `main()` function that creates a root command - **setting configurations** by reading in configuration files (e.g. the sdk config file). - **adding any flags** to it, such as `--chain-id`. -- **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../core/encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. +- **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../05-encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. - **adding subcommand** for all the possible user interactions, including [transaction commands](#transaction-commands) and [query commands](#query-commands). The `main()` function finally creates an executor and [execute](https://godoc.org/github.com/spf13/cobra#Command.Execute) the root command. See an example of `main()` function from the `simapp` application: @@ -52,7 +48,7 @@ Every application CLI first constructs a root command, then adds functionality b The root command (called `rootCmd`) is what the user first types into the command line to indicate which application they wish to interact with. The string used to invoke the command (the "Use" field) is typically the name of the application suffixed with `-d`, e.g. `simd` or `gaiad`. The root command typically includes the following commands to support basic functionality in the application. -- **Status** command from the SDK rpc client tools, which prints information about the status of the connected [`Node`](../core/node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. +- **Status** command from the SDK rpc client tools, which prints information about the status of the connected [`Node`](../03-node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. - **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/keys) from the SDK client tools, which includes a collection of subcommands for using the key functions in the SDK crypto tools, including adding a new key and saving it to the keyring, listing all public keys stored in the keyring, and deleting a key. For example, users can type `simd keys add ` to add a new key and save an encrypted copy to the keyring, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](../run-node/keyring.md). - **Server** commands from the SDK server package. These commands are responsible for providing the mechanisms necessary to start an ABCI Tendermint application and provides the CLI framework (based on [cobra](github.com/spf13/cobra)) necessary to fully bootstrap an application. The package exposes two core functions: `StartCmd` and `ExportCmd` which creates commands to start the application and export state respectively. Click [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/server) to learn more. - [**Transaction**](#transaction-commands) commands. @@ -76,7 +72,7 @@ The root-level `status` and `keys` subcommands are common across most applicatio ### Transaction Commands -[Transactions](./transactions.md) are objects wrapping [`Msg`s](../building-modules/messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: +[Transactions](./01-transactions.md) are objects wrapping [`Msg`s](../building-modules/02-messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L86-L92 @@ -84,7 +80,7 @@ This `txCmd` function adds all the transaction available to end-users for the ap - **Sign command** from the [`auth`](../../x/auth/spec/README.md) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, the signing command is necessary for every application. - **Broadcast command** from the SDK client tools, to broadcast transactions. -- **All [module transaction commands](../building-modules/module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddTxCommands()` function. +- **All [module transaction commands](../building-modules/09-module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddTxCommands()` function. Here is an example of a `txCmd` aggregating these subcommands from the `simapp` application: @@ -92,7 +88,7 @@ Here is an example of a `txCmd` aggregating these subcommands from the `simapp` ### Query Commands -[**Queries**](../building-modules/messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: +[**Queries**](../building-modules/02-messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L86-L92 @@ -102,7 +98,7 @@ This `queryCmd` function adds all the queries available to end-users for the app - **Account command** from the `auth` module, which displays the state (e.g. account balance) of an account given an address. - **Validator command** from the SDK rpc client tools, which displays the validator set of a given height. - **Block command** from the SDK rpc client tools, which displays the block data for a given height. -- **All [module query commands](../building-modules/module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddQueryCommands()` function. +- **All [module query commands](../building-modules/09-module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddQueryCommands()` function. Here is an example of a `queryCmd` aggregating subcommands from the `simapp` application: @@ -114,7 +110,7 @@ Flags are used to modify commands; developers can include them in a `flags.go` f A _persistent_ flag (as opposed to a _local_ flag) added to a command transcends all of its children: subcommands will inherit the configured values for these flags. Additionally, all flags have default values when they are added to commands; some toggle an option off but others are empty values that the user needs to override to create valid commands. A flag can be explicitly marked as _required_ so that an error is automatically thrown if the user does not provide a value, but it is also acceptable to handle unexpected missing flags differently. -Flags are added to commands directly (generally in the [module's CLI file](../building-modules/module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `simapp` application: +Flags are added to commands directly (generally in the [module's CLI file](../building-modules/09-module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `simapp` application: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118-L119 @@ -153,4 +149,4 @@ The `InterceptConfigsPreRunHandler` call creates a viper literal, default `serve ## Next {hide} -Learn about [events](./events.md) {hide} +Learn about [events](./07-events.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/events.md b/versioned_docs/version-0.45/develop/advanced-concepts/07-events.md similarity index 89% rename from versioned_docs/version-0.45/develop/advanced-concepts/events.md rename to versioned_docs/version-0.45/develop/advanced-concepts/07-events.md index d62663abd..1ab265b91 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/events.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/07-events.md @@ -1,14 +1,10 @@ - - # Events `Event`s are objects that contain information about the execution of the application. They are mainly used by service providers like block explorers and wallet to track the execution of various messages and index transactions. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/overview-app.md) {prereq} - [Tendermint Documentation on Events](https://docs.tendermint.com/master/spec/abci/abci.html#events) {prereq} ## Events @@ -28,16 +24,16 @@ To parse the attribute values as strings, make sure to add `'` (single quotes) a ::: Events, the `type` and `attributes` are defined on a **per-module basis** in the module's -`/types/events.go` file, and triggered from the module's Protobuf [`Msg` service](../building-modules/msg-services.md) +`/types/events.go` file, and triggered from the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md) by using the [`EventManager`](#eventmanager). In addition, each module documents its Events under `spec/xx_events.md`. Events are returned to the underlying consensus engine in the response of the following ABCI messages: -- [`BeginBlock`](./baseapp.md#beginblock) -- [`EndBlock`](./baseapp.md#endblock) -- [`CheckTx`](./baseapp.md#checktx) -- [`DeliverTx`](./baseapp.md#delivertx) +- [`BeginBlock`](./00-baseapp.md#beginblock) +- [`EndBlock`](./00-baseapp.md#endblock) +- [`CheckTx`](./00-baseapp.md#checktx) +- [`DeliverTx`](./00-baseapp.md#delivertx) ### Examples @@ -46,8 +42,8 @@ The following examples show how to query Events using the SDK. | Event | Description | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tx.height=23` | Query all transactions at height 23 | -| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/msg-services.md). Note the `'`s around the value. | -| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | +| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/03-msg-services.md). Note the `'`s around the value. | +| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/03-msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | | `message.module='bank'` | Query all transactions containing messages from the x/bank module. Note the `'`s around the value. | | `create_validator.validator='cosmosval1...'` | x/staking-specific Event, see [x/staking SPEC](../../../cosmos-sdk/x/staking/spec/07_events.md). | @@ -67,7 +63,7 @@ an Event in the `EventManager`. Module developers should handle Event emission via the `EventManager#EmitEvent` in each message `Handler` and in each `BeginBlock`/`EndBlock` handler. The `EventManager` is accessed via -the [`Context`](./context.md), where Event emission generally follows this pattern: +the [`Context`](./02-context.md), where Event emission generally follows this pattern: ```go ctx.EventManager().EmitEvent( @@ -84,7 +80,7 @@ func NewHandler(keeper Keeper) sdk.Handler { switch msg := msg.(type) { ``` -See the [`Msg` services](../building-modules/msg-services.md) concept doc for a more detailed +See the [`Msg` services](../building-modules/03-msg-services.md) concept doc for a more detailed view on how to typically implement Events and use the `EventManager` in modules. ## Subscribing to Events @@ -124,7 +120,7 @@ The `type` and `attribute` value of the `query` allow you to filter the specific } ``` -where `senderAddress` is an address following the [`AccAddress`](../basics/accounts.md#addresses) format. +where `senderAddress` is an address following the [`AccAddress`](../high-level-concepts/03-accounts.md#addresses) format. ## Typed Events (coming soon) @@ -134,4 +130,4 @@ The Typed Events proposal has not yet been fully implemented. Documentation is n ## Next {hide} -Learn about SDK [telemetry](./telemetry.md) {hide} +Learn about SDK [telemetry](./11-telemetry.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/grpc_rest.md b/versioned_docs/version-0.45/develop/advanced-concepts/08-grpc_rest.md similarity index 92% rename from versioned_docs/version-0.45/develop/advanced-concepts/grpc_rest.md rename to versioned_docs/version-0.45/develop/advanced-concepts/08-grpc_rest.md index c4f1feb17..f7f581205 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/grpc_rest.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/08-grpc_rest.md @@ -1,7 +1,3 @@ - - # gRPC, REST, and Tendermint Endpoints This document presents an overview of all the endpoints a node exposes: gRPC, REST as well as some other endpoints. {synopsis} @@ -34,11 +30,11 @@ Please see [issue #8392](https://github.com/cosmos/cosmos-sdk/issues/8392) for m Cosmos SDK v0.40 introduced Protobuf as the main [encoding](./encoding) library, and this brings a wide range of Protobuf-based tools that can be plugged into the SDK. One such tool is [gRPC](https://grpc.io), a modern open source high performance RPC framework that has decent client support in several languages. -Each module exposes a [Protobuf `Query` service](../building-modules/messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: +Each module exposes a [Protobuf `Query` service](../building-modules/02-messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-rc0/server/types/app.go#L39-L41 -Note: It is not possible to expose any [Protobuf `Msg` service](../building-modules/messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../run-node/txs.html) for more information. +Note: It is not possible to expose any [Protobuf `Msg` service](../building-modules/02-messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../run-node/txs.html) for more information. The `grpc.Server` is a concrete gRPC server, which spawns and serves all gRPC query requests and a broadcast transaction request. This server can be configured inside `~/.simapp/config/app.toml`: @@ -51,7 +47,7 @@ The `grpc.Server` is a concrete gRPC server, which spawns and serves all gRPC qu Once the gRPC server is started, you can send requests to it using a gRPC client. Some examples are given in our [Interact with the Node](../run-node/interact-node.md#using-grpc) tutorial. -An overview of all available gRPC endpoints shipped with the Cosmos SDK is [Protobuf documention](./proto-docs.md). +An overview of all available gRPC endpoints shipped with the Cosmos SDK is [Protobuf documention](./14-proto-docs.md). ## REST Server @@ -100,7 +96,7 @@ Some Tendermint RPC endpoints are directly related to the Cosmos SDK: - `/store/{path}`: this will query the store directly. - `/p2p/filter/addr/{port}`: this will return a filtered list of the node's P2P peers by address port. - `/p2p/filter/id/{id}`: this will return a filtered list of the node's P2P peers by ID. -- `/broadcast_tx_{aync,async,commit}`: these 3 endpoint will broadcast a transaction to other peers. CLI, gRPC and REST expose [a way to broadcast transations](./transactions.md#broadcasting-the-transaction), but they all use these 3 Tendermint RPCs under the hood. +- `/broadcast_tx_{aync,async,commit}`: these 3 endpoint will broadcast a transaction to other peers. CLI, gRPC and REST expose [a way to broadcast transations](./01-transactions.md#broadcasting-the-transaction), but they all use these 3 Tendermint RPCs under the hood. ## Comparison Table @@ -113,4 +109,4 @@ Some Tendermint RPC endpoints are directly related to the Cosmos SDK: ## Next {hide} -Learn about [the CLI](./cli.md) {hide} +Learn about [the CLI](./06-cli.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/ocap.md b/versioned_docs/version-0.45/develop/advanced-concepts/09-ocap.md similarity index 96% rename from versioned_docs/version-0.45/develop/advanced-concepts/ocap.md rename to versioned_docs/version-0.45/develop/advanced-concepts/09-ocap.md index 833efa646..fb38c755d 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/ocap.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/09-ocap.md @@ -1,7 +1,3 @@ - - # Object-Capability Model ## Intro @@ -76,4 +72,4 @@ The following diagram shows the current dependencies between keepers. ## Next {hide} -Learn about the [`runTx` middleware](./runtx_middleware.md) {hide} +Learn about the [`runTx` middleware](./12-runtx_middleware.md) {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/telemetry.md b/versioned_docs/version-0.45/develop/advanced-concepts/10-telemetry.md similarity index 99% rename from versioned_docs/version-0.45/develop/advanced-concepts/telemetry.md rename to versioned_docs/version-0.45/develop/advanced-concepts/10-telemetry.md index 9e434eef2..a9fdb5105 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/telemetry.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/10-telemetry.md @@ -1,7 +1,3 @@ - - # Telemetry Gather relevant insights about your application and modules with custom metrics and telemetry. {synopsis} @@ -142,4 +138,4 @@ The following examples expose too much cardinality and may not even prove to be ## Next {hide} -Learn about the [object-capability](./ocap.md) model {hide} +Learn about the [object-capability](./09-ocap.md) model {hide} diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/runtx_middleware.md b/versioned_docs/version-0.45/develop/advanced-concepts/11-runtx_middleware.md similarity index 99% rename from versioned_docs/version-0.45/develop/advanced-concepts/runtx_middleware.md rename to versioned_docs/version-0.45/develop/advanced-concepts/11-runtx_middleware.md index 9c978fbbe..3b3535a1a 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/runtx_middleware.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/11-runtx_middleware.md @@ -1,7 +1,3 @@ - - # RunTx recovery middleware `BaseApp.runTx()` function handles Golang panics that might occur during transactions execution, for example, keeper has faced an invalid state and paniced. diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/simulation.md b/versioned_docs/version-0.45/develop/advanced-concepts/12-simulation.md similarity index 99% rename from versioned_docs/version-0.45/develop/advanced-concepts/simulation.md rename to versioned_docs/version-0.45/develop/advanced-concepts/12-simulation.md index 9b838b40b..2ce65a954 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/simulation.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/12-simulation.md @@ -1,7 +1,3 @@ - - # Cosmos Blockchain Simulator The Cosmos SDK offers a full fledged simulation framework to fuzz test every diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/upgrade.md b/versioned_docs/version-0.45/develop/advanced-concepts/13-upgrade.md similarity index 97% rename from versioned_docs/version-0.45/develop/advanced-concepts/upgrade.md rename to versioned_docs/version-0.45/develop/advanced-concepts/13-upgrade.md index c1cf37acd..31ace074f 100644 --- a/versioned_docs/version-0.45/develop/advanced-concepts/upgrade.md +++ b/versioned_docs/version-0.45/develop/advanced-concepts/13-upgrade.md @@ -1,7 +1,3 @@ - - # In-Place Store Migrations ::: warning @@ -14,7 +10,7 @@ The Cosmos SDK uses two methods to perform upgrades. - Exporting the entire application state to a JSON file using the `export` CLI command, making changes, and then starting a new binary with the changed JSON file as the genesis file. See [Chain Upgrade Guide to v0.42](/v0.42/migrations/chain-upgrade-guide-040.html). -- Version v0.44 and later can perform upgrades in place to significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/upgrade.md) to set up your application modules to take advantage of in-place upgrades. +- Version v0.44 and later can perform upgrades in place to significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/13-upgrade.md) to set up your application modules to take advantage of in-place upgrades. This document provides steps to use the In-Place Store Migrations upgrade method. @@ -61,7 +57,7 @@ app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgrad }) ``` -To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../building-modules/upgrade.md). +To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../building-modules/13-upgrade.md). ### Order Of Migrations diff --git a/versioned_docs/version-0.45/develop/advanced-concepts/README.md b/versioned_docs/version-0.45/develop/advanced-concepts/README.md deleted file mode 100644 index a6853b418..000000000 --- a/versioned_docs/version-0.45/develop/advanced-concepts/README.md +++ /dev/null @@ -1,28 +0,0 @@ - - -# Core Concepts - -This repository contains reference documentation on the core concepts of the Cosmos SDK. - -1. [`BaseApp`](./baseapp.md) -2. [Transaction](./transactions.md) -3. [Context](./context.md) -4. [Node Client](./node.md) -5. [Store](./store.md) -6. [Encoding](./encoding.md) -7. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md) -8. [Command-Line Interface](./cli.md) -9. [Events](./events.md) -10. [Telemetry](./telemetry.md) -11. [Object-Capabilities](./ocap.md) -12. [RunTx recovery middleware](./runtx_middleware.md) -13. [Simulation](./simulation.md) -14. [Protobuf documentation](./proto-docs.md) -15. [In-Place Store Migrations](./upgrade.md) - -After reading about the core concepts, check the [IBC documentation](../ibc/README.md) to learn more -about the IBC core concepts and how to integrate IBC in your application. diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/app-anatomy.md b/versioned_docs/version-0.45/develop/high-level-concepts/00-overview-app.md similarity index 70% rename from versioned_docs/version-0.45/develop/high-level-concepts/app-anatomy.md rename to versioned_docs/version-0.45/develop/high-level-concepts/00-overview-app.md index 0373d24aa..2d3b4a105 100644 --- a/versioned_docs/version-0.45/develop/high-level-concepts/app-anatomy.md +++ b/versioned_docs/version-0.45/develop/high-level-concepts/00-overview-app.md @@ -1,14 +1,10 @@ - - # Anatomy of an SDK Application This document describes the core parts of a Cosmos SDK application. Throughout the document, a placeholder application named `app` will be used. {synopsis} ## Node Client -The Daemon, or [Full-Node Client](../core/node.md), is the core process of an SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes and update their state-machine as new blocks come in. +The Daemon, or [Full-Node Client](../core/03-node.md), is the core process of an SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes and update their state-machine as new blocks come in. ``` ^ +-------------------------------+ ^ @@ -28,9 +24,9 @@ Blockchain Node | | Consensus | | v +-------------------------------+ v ``` -The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../core/node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). +The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../core/03-node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). -Once the main binary is built, the node can be started by running the [`start` command](../core/node.md#start-command). This command function primarily does three things: +Once the main binary is built, the node can be started by running the [`start` command](../core/03-node.md#start-command). This command function primarily does three things: 1. Create an instance of the state-machine defined in [`app.go`](#core-application-file). 2. Initialize the state-machine with the latest known state, extracted from the `db` stored in the `~/.app/data` folder. At this point, the state-machine is at height `appBlockHeight`. @@ -44,12 +40,12 @@ In general, the core of the state-machine is defined in a file called `app.go`. The first thing defined in `app.go` is the `type` of the application. It is generally comprised of the following parts: -- **A reference to [`baseapp`](../core/baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by Tendermint to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://tendermint.com/docs/spec/abci/abci.html#overview) and the [routing logic](../core/baseapp.md#routing). -- **A list of store keys**. The [store](../core/store.md), which contains the entire state, is implemented as a [`multistore`](../core/store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. -- **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../building-modules/keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. -- **A reference to an [`appCodec`](../core/encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../core/encoding.md). -- **A reference to a [`legacyAmino`](../core/encoding.md) codec.** Some parts of the SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicity use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. -- **A reference to a [module manager](../building-modules/module-manager.md#manager)** and a [basic module manager](../building-modules/module-manager.md#basicmanager). The module manager is an object that contains a list of the application's module. It facilitates operations related to these modules, like registering their [`Msg` service](../core/baseapp.md#msg-services) and [gRPC `Query` service](../core/baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). +- **A reference to [`baseapp`](../../develop/advanced-concepts/00-baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by Tendermint to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://tendermint.com/docs/spec/abci/abci.html#overview) and the [routing logic](../../develop/advanced-concepts/00-baseapp.md#routing). +- **A list of store keys**. The [store](../core/04-store.md), which contains the entire state, is implemented as a [`multistore`](../core/04-store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. +- **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. +- **A reference to an [`appCodec`](../core/05-encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../core/05-encoding.md). +- **A reference to a [`legacyAmino`](../core/05-encoding.md) codec.** Some parts of the SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicity use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. +- **A reference to a [module manager](../building-modules/01-module-manager.md#manager)** and a [basic module manager](../building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's module. It facilitates operations related to these modules, like registering their [`Msg` service](../../develop/advanced-concepts/00-baseapp.md#msg-services) and [gRPC `Query` service](../../develop/advanced-concepts/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). See an example of application type definition from `simapp`, the SDK's own app used for demo and testing purposes: @@ -57,23 +53,23 @@ See an example of application type definition from `simapp`, the SDK's own app u ### Constructor Function -This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/node.md#start-command) of the application's daemon command. +This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/03-node.md#start-command) of the application's daemon command. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 Here are the main actions performed by this function: -- Instantiate a new [`codec`](../core/encoding.md) and initialize the `codec` of each of the application's module using the [basic manager](../building-modules/module-manager.md#basicmanager) +- Instantiate a new [`codec`](../core/05-encoding.md) and initialize the `codec` of each of the application's module using the [basic manager](../building-modules/01-module-manager.md#basicmanager) - Instantiate a new application with a reference to a `baseapp` instance, a codec and all the appropriate store keys. - Instantiate all the [`keeper`s](#keeper) defined in the application's `type` using the `NewKeeper` function of each of the application's modules. Note that `keepers` must be instantiated in the correct order, as the `NewKeeper` of one module might require a reference to another module's `keeper`. -- Instantiate the application's [module manager](../building-modules/module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. -- With the module manager, initialize the application's [`Msg` services](../core/baseapp.md#msg-services), [gRPC `Query` services](../core/baseapp.md#grpc-query-services), [legacy `Msg` routes](../core/baseapp.md#routing) and [legacy query routes](../core/baseapp.md#query-routing). When a transaction is relayed to the application by Tendermint via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The SDK still supports legacy `Msg`s and legacy Tendermint queries, which are routed using respectively the legacy `Msg` routes and the legacy query routes. -- With the module manager, register the [application's modules' invariants](../building-modules/invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../building-modules/invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry will be triggered (usually the chain is halted). This is useful to make sure no critical bug goes unnoticed and produces long-lasting effects that would be hard to fix. +- Instantiate the application's [module manager](../building-modules/01-module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. +- With the module manager, initialize the application's [`Msg` services](../../develop/advanced-concepts/00-baseapp.md#msg-services), [gRPC `Query` services](../../develop/advanced-concepts/00-baseapp.md#grpc-query-services), [legacy `Msg` routes](../../develop/advanced-concepts/00-baseapp.md#routing) and [legacy query routes](../../develop/advanced-concepts/00-baseapp.md#query-routing). When a transaction is relayed to the application by Tendermint via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The SDK still supports legacy `Msg`s and legacy Tendermint queries, which are routed using respectively the legacy `Msg` routes and the legacy query routes. +- With the module manager, register the [application's modules' invariants](../building-modules/07-invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../building-modules/07-invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry will be triggered (usually the chain is halted). This is useful to make sure no critical bug goes unnoticed and produces long-lasting effects that would be hard to fix. - With the module manager, set the order of execution between the `InitGenesis`, `BeginBlocker` and `EndBlocker` functions of each of the [application's modules](#application-module-interface). Note that not all modules implement these functions. - Set the remainer of application's parameters: - [`InitChainer`](#initchainer): used to initialize the application when it is first started. - [`BeginBlocker`, `EndBlocker`](#beginblocker-and-endlbocker): called at the beginning and the end of every block). - - [`anteHandler`](../core/baseapp.md#antehandler): used to handle fees and signature verification. + - [`anteHandler`](../../develop/advanced-concepts/00-baseapp.md#antehandler): used to handle fees and signature verification. - Mount the stores. - Return the application. @@ -87,7 +83,7 @@ See an example of application constructor from `simapp`: The `InitChainer` is a function that initializes the state of the application from a genesis file (i.e. token balances of genesis accounts). It is called when the application receives the `InitChain` message from the Tendermint engine, which happens when the node is started at `appBlockHeight == 0` (i.e. on genesis). The application must set the `InitChainer` in its [constructor](#constructor-function) via the [`SetInitChainer`](https://godoc.org/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetInitChainer) method. -In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn will call the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../building-modules/module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#application-constructor), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. +In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../building-modules/08-genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn will call the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../building-modules/01-module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#application-constructor), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. See an example of an `InitChainer` from `simapp`: @@ -97,7 +93,7 @@ See an example of an `InitChainer` from `simapp`: The SDK offers developers the possibility to implement automatic execution of code as part of their application. This is implemented through two function called `BeginBlocker` and `EndBlocker`. They are called when the application receives respectively the `BeginBlock` and `EndBlock` messages from the Tendermint engine, which happens at the beginning and at the end of each block. The application must set the `BeginBlocker` and `EndBlocker` in its [constructor](#constructor-function) via the [`SetBeginBlocker`](https://godoc.org/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetBeginBlocker) and [`SetEndBlocker`](https://godoc.org/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetEndBlocker) methods. -In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../building-modules/beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn will call the `BeginBLock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BegingBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlock` and `SetOrderEndBlock` methods respectively. This is done via the [module manager](../building-modules/module-manager.md) in the [application's constructor](#application-constructor), and the `SetOrderBeginBlock` and `SetOrderEndBlock` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. +In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../building-modules/beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn will call the `BeginBLock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BegingBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlock` and `SetOrderEndBlock` methods respectively. This is done via the [module manager](../building-modules/01-module-manager.md) in the [application's constructor](#application-constructor), and the `SetOrderBeginBlock` and `SetOrderEndBlock` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in `BeginBlocker` or `EndBlocker`, and must also be careful not to make them too computationally expensive, as [gas](./gas-fees.md) does not constrain the cost of `BeginBlocker` and `EndBlocker` execution. @@ -117,7 +113,7 @@ Here are descriptions of what each of the four fields means: - You can read more about Any in [ADR-19](../architecture/adr-019-protobuf-state-encoding.md#usage-of-any-to-encode-interfaces). - To go more into details, the SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/gogo/protobuf). By default, the [gogo protobuf implementation of `Any`](https://godoc.org/github.com/gogo/protobuf/types) uses [global type registration](https://github.com/gogo/protobuf/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could registry a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). - `Marshaler`: the default codec used throughout the SDK. It is composed of a `BinaryCodec` used to encode and decode state, and a `JSONCodec` used to output data to the users (for example in the [CLI](#cli)). By default, the SDK uses Protobuf as `Marshaler`. -- `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/transactions.md). +- `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/01-transactions.md). - `Amino`: Some legacy parts of the SDK still use Amino for backwards-compatibility. Each module exposes a `RegisterLegacyAmino` method to register the module's specific types within Amino. This `Amino` codec should not be used by app developers anymore, and will be removed in future releases. The SDK exposes a `MakeTestEncodingConfig` function used to create a `EncodingConfig` for the app constructor (`NewApp`). It uses Protobuf as a default `Marshaler`. @@ -129,19 +125,19 @@ See an example of a `MakeTestEncodingConfig` from `simapp`: ## Modules -[Modules](../building-modules/intro.md) are the heart and soul of SDK applications. They can be considered as state-machines within the state-machine. When a transaction is relayed from the underlying Tendermint engine via the ABCI to the application, it is routed by [`baseapp`](../core/baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. For developers, most of the work involved in building an SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the SDK's `x/` folder, which contains already-built modules). +[Modules](../building-modules/intro.md) are the heart and soul of SDK applications. They can be considered as state-machines within the state-machine. When a transaction is relayed from the underlying Tendermint engine via the ABCI to the application, it is routed by [`baseapp`](../../develop/advanced-concepts/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. For developers, most of the work involved in building an SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the SDK's `x/` folder, which contains already-built modules). ### Application Module Interface -Modules must implement [interfaces](../building-modules/module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../building-modules/module-manager.md#appmodulebasic) and [`AppModule`](../building-modules/module-manager.md#appmodule). The former implements basic non-dependant elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are defined in a file called `./module.go`. +Modules must implement [interfaces](../building-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../building-modules/01-module-manager.md#appmodulebasic) and [`AppModule`](../building-modules/01-module-manager.md#appmodule). The former implements basic non-dependant elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are defined in a file called `./module.go`. -`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are are called from the `module manager`(../building-modules/module-manager.md#manager), which manages the application's collection of modules. +`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are are called from the `module manager`(../building-modules/01-module-manager.md#manager), which manages the application's collection of modules. ### `Msg` Services Each module defines two [Protobuf services](https://developers.google.com/protocol-buffers/docs/proto#services): one `Msg` service to handle messages, and one gRPC `Query` service to handle queries. If we consider the module as a state-machine, then a `Msg` service is a set of state transition RPC methods. Each Protobuf `Msg` service method is 1:1 related to a Protobuf request type, which must implement `sdk.Msg` interface. -Note that `sdk.Msg`s are bundled in [transactions](../core/transactions.md), and each transaction contains one or multiple messages. +Note that `sdk.Msg`s are bundled in [transactions](../core/01-transactions.md), and each transaction contains one or multiple messages. When a valid block of transactions is received by the full-node, Tendermint relays each one to the application via [`DeliverTx`](https://tendermint.com/docs/app-dev/abci-spec.html#delivertx). Then, the application handles the transaction: @@ -150,7 +146,7 @@ When a valid block of transactions is received by the full-node, Tendermint rela 3. `sdk.Msg`s are encoded using Protobuf [`Any`s](#register-codec). By analyzing each `Any`'s `type_url`, baseapp's `msgServiceRouter` routes the `sdk.Msg` to the corresponding module's `Msg` service. 4. If the message is successfully processed, the state is updated. -For a more details look at a transaction [lifecycle](./tx-lifecycle.md). +For a more details look at a transaction [lifecycle](./01-tx-lifecycle.md). Module developers create custom `Msg` services when they build their own module. The general practice is to define the `Msg` Protobuf service in a `tx.proto` file. For example, the `x/bank` module defines a service with two methods to transfer tokens: @@ -172,7 +168,7 @@ Finally, each module should also implement the `RegisterServices` method as part ### Keeper -[`Keepers`](../building-modules/keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../core/ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). +[`Keepers`](../building-modules/06-keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../core/ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). `Keepers` are generally defined in a file called `keeper.go`. It contains the `keeper`'s type definition and methods. @@ -190,10 +186,10 @@ Each module defines command-line commands, gRPC services and REST routes to be e #### CLI -Generally, the [commands related to a module](../building-modules/module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands in two category, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go` respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): +Generally, the [commands related to a module](../building-modules/09-module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands in two category, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go` respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): - Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each [message type](#message-types) defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The SDK handles signing and the addition of other transaction metadata. -- Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../core/baseapp.md#query-routing), which routes them to the appropriate [querier](#querier) the `queryRoute` parameter supplied. +- Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../../develop/advanced-concepts/00-baseapp.md#query-routing), which routes them to the appropriate [querier](#querier) the `queryRoute` parameter supplied. #### gRPC @@ -214,7 +210,7 @@ The SDK also provides a development endpoint to generate [Swagger](https://swagg #### Legacy API REST Endpoints -The [module's Legacy REST interface](../building-modules/module-interfaces.md#legacy-rest) lets users generate transactions and query the state through REST calls to the application's Legacy API Service. REST routes are defined in a file `client/rest/rest.go`, which is composed of: +The [module's Legacy REST interface](../building-modules/09-module-interfaces.md#legacy-rest) lets users generate transactions and query the state through REST calls to the application's Legacy API Service. REST routes are defined in a file `client/rest/rest.go`, which is composed of: - A `RegisterRoutes` function, which registers each route defined in the file. This function is called from the [main application's interface](#application-interfaces) for each module used within the application. The router used in the SDK is [Gorilla's mux](https://github.com/gorilla/mux). - Custom request type definitions for each query or transaction creation function that needs to be exposed. These custom request types build on the base `request` type of the Cosmos SDK: @@ -227,7 +223,7 @@ These Legacy API endpoints are present in the SDK for backward compatibility pur [Interfaces](#command-line-grpc-services-and-rest-interfaces) let end-users interact with full-node clients. This means querying data from the full-node or creating and sending new transactions to be relayed by the full-node and eventually included in a block. -The main interface is the [Command-Line Interface](../core/cli.md). The CLI of an SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and defined in a file called `appd/main.go`. The file contains: +The main interface is the [Command-Line Interface](../core/06-cli.md). The CLI of an SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and defined in a file called `appd/main.go`. The file contains: - **A `main()` function**, which is executed to build the `appd` interface client. This function prepares each command and adds them to the `rootCmd` before building them. At the root of `appd`, the function adds generic commands like `status`, `keys` and `config`, query commands, tx commands and `rest-server`. - **Query commands** are added by calling the `queryCmd` function. This function returns a Cobra command that contains the query commands defined in each of the application's modules (passed as an array of `sdk.ModuleClients` from the `main()` function), as well as some other lower level query commands such as block or validator queries. Query command are called by using the command `appd query [query]` of the CLI. @@ -261,4 +257,4 @@ For building the application, a [Makefile](https://en.wikipedia.org/wiki/Makefil ## Next {hide} -Learn more about the [Lifecycle of a transaction](./tx-lifecycle.md) {hide} +Learn more about the [Lifecycle of a transaction](./01-tx-lifecycle.md) {hide} diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/tx-lifecycle.md b/versioned_docs/version-0.45/develop/high-level-concepts/01-tx-lifecycle.md similarity index 81% rename from versioned_docs/version-0.45/develop/high-level-concepts/tx-lifecycle.md rename to versioned_docs/version-0.45/develop/high-level-concepts/01-tx-lifecycle.md index fa51eef1c..06301418f 100644 --- a/versioned_docs/version-0.45/develop/high-level-concepts/tx-lifecycle.md +++ b/versioned_docs/version-0.45/develop/high-level-concepts/01-tx-lifecycle.md @@ -1,10 +1,6 @@ - - # Transaction Lifecycle -This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../core/transactions.md). The transaction will be referred to as `Tx`. {synopsis} +This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../advanced-concepts/01-transactions.md). The transaction will be referred to as `Tx`. {synopsis} ### Pre-requisite Readings @@ -14,7 +10,7 @@ This document describes the lifecycle of a transaction from creation to committe ### Transaction Creation -One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../core/cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: +One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../advanced-concepts/06-cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: ```bash [appname] tx [command] [args] [flags] @@ -22,11 +18,11 @@ One of the main application interfaces is the command-line interface. The transa This command will automatically **create** the transaction, **sign** it using the account's private key, and **broadcast** it to the specified peer node. -There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](./accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds will be drawn from the specified `from` address. +There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](./03-accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds will be drawn from the specified `from` address. #### Gas and Fees -Additionally, there are several [flags](../core/cli.md) users can use to indicate how much they are willing to pay in [fees](./gas-fees.md): +Additionally, there are several [flags](../advanced-concepts/06-cli.md) users can use to indicate how much they are willing to pay in [fees](./gas-fees.md): - `--gas` refers to how much [gas](./gas-fees.md), which represents computational resources, `Tx` consumes. Gas is dependent on the transaction and is not precisely calculated until execution, but can be estimated by providing `auto` as the value for `--gas`. - `--gas-adjustment` (optional) can be used to scale `gas` up in order to avoid underestimating. For example, users can specify their gas adjustment as 1.5 to use 1.5 times the estimated gas. @@ -48,7 +44,7 @@ appd tx send 1000uatom --from --gas auto --ga #### Other Transaction Creation Methods -The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../core/grpc_rest.md) or some other entrypoint defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). +The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../advanced-concepts/08-grpc_rest.md) or some other entrypoint defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). ## Addition to Mempool @@ -68,7 +64,7 @@ are not empty, enforcing nonnegative numbers, and other logic specified in the d **_Stateful_** checks validate transactions and messages based on a committed state. Examples include checking that the relevant values exist and are able to be transacted with, the address has sufficient funds, and the sender is authorized or has the correct ownership to transact. -At any given moment, full-nodes typically have [multiple versions](../core/baseapp.md#volatile-states) +At any given moment, full-nodes typically have [multiple versions](../../develop/advanced-concepts/00-baseapp.md#volatile-states) of the application's internal state for different purposes. For example, nodes will execute state changes while in the process of verifying transactions, but still need a copy of the last committed state in order to answer queries - they should not respond using state with uncommitted changes. @@ -79,12 +75,12 @@ through several steps, beginning with decoding `Tx`. ### Decoding -When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../core/encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../core/baseapp.md#runtx-and-runmsgs) function is called to run in `runTxModeCheck` mode, meaning the function will run all checks but exit before executing messages and writing state changes. +When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../advanced-concepts/05-encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../../develop/advanced-concepts/00-baseapp.md#runtx-and-runmsgs) function is called to run in `runTxModeCheck` mode, meaning the function will run all checks but exit before executing messages and writing state changes. ### ValidateBasic -Messages ([`sdk.Msg`](../core/transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. -To discard obviously invalid messages, the BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../core/baseapp.md#checktx) and [`DeliverTx`](../core/baseapp.md#delivertx)) transactions. +Messages ([`sdk.Msg`](../core/01-transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. +To discard obviously invalid messages, the BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../../develop/advanced-concepts/00-baseapp.md#checktx) and [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx)) transactions. `ValidateBasic` can include only **stateless** checks (the checks that do not require access to the state). #### Guideline @@ -94,7 +90,7 @@ Other validation operations must be performed when [handling a message](../build Example, if the message is to send coins from one address to another, `ValidateBasic` likely checks for non-empty addresses and a non-negative coin amount, but does not require knowledge of state such as the account balance of an address. -See also [Msg Service Validation](../building-modules/msg-services.md#Validation). +See also [Msg Service Validation](../building-modules/03-msg-services.md#Validation). ### AnteHandler @@ -106,7 +102,7 @@ For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/aut ### Gas -The [`Context`](../core/context.md), which keeps a `GasMeter` that will track how much gas has been used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed so during execution, ever exceeds `GasWanted`, the execution will stop and the changes made to the cached copy of the state won't be committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. +The [`Context`](../core/02-context.md), which keeps a `GasMeter` that will track how much gas has been used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed so during execution, ever exceeds `GasWanted`, the execution will stop and the changes made to the cached copy of the state won't be committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. ### Discard or Addition to Mempool @@ -192,10 +188,10 @@ explicitly ordered in the block proposal. ### DeliverTx -The `DeliverTx` ABCI function defined in [`BaseApp`](../core/baseapp.md) does the bulk of the +The `DeliverTx` ABCI function defined in [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md) does the bulk of the state transitions: it is run for each transaction in the block in sequential order as committed to during consensus. Under the hood, `DeliverTx` is almost identical to `CheckTx` but calls the -[`runTx`](../core/baseapp.md#runtx) function in deliver mode instead of check mode. +[`runTx`](../../develop/advanced-concepts/00-baseapp.md#runtx) function in deliver mode instead of check mode. Instead of using their `checkState`, full-nodes use `deliverState`: - **Decoding:** Since `DeliverTx` is an ABCI call, `Tx` is received in the encoded `[]byte` form. @@ -208,10 +204,10 @@ Instead of using their `checkState`, full-nodes use `deliverState`: to each node - differing values across nodes would yield nondeterministic results. - **`MsgServiceRouter`:** While `CheckTx` would have exited, `DeliverTx` continues to run - [`runMsgs`](../core/baseapp.md#runtx-and-runmsgs) to fully execute each `Msg` within the transaction. + [`runMsgs`](../../develop/advanced-concepts/00-baseapp.md#runtx-and-runmsgs) to fully execute each `Msg` within the transaction. Since the transaction may have messages from different modules, `BaseApp` needs to know which module - to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/msg-services.md). - For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/msg-services.md#handler-type) within the module. + to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). + For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/01-module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/03-msg-services.md#handler-type) within the module. - **`Msg` service:** a Protobuf `Msg` service, a step up from `AnteHandler`, is responsible for executing each message in the `Tx` and causes state transitions to persist in `deliverTxState`. @@ -235,8 +231,8 @@ not they should commit the state changes. When they receive enough validator votes (2/3+ _precommits_ weighted by voting power), full nodes commit to a new block to be added to the blockchain and finalize the state transitions in the application layer. A new state root is generated to serve as -a merkle proof for the state transitions. Applications use the [`Commit`](../core/baseapp.md#commit) -ABCI method inherited from [Baseapp](../core/baseapp.md); it syncs all the state transitions by +a merkle proof for the state transitions. Applications use the [`Commit`](../../develop/advanced-concepts/00-baseapp.md#commit) +ABCI method inherited from [Baseapp](../../develop/advanced-concepts/00-baseapp.md); it syncs all the state transitions by writing the `deliverState` into the application's internal state. As soon as the state changes are committed, `checkState` start afresh from the most recently committed state and `deliverState` resets to `nil` in order to be consistent and reflect the changes. @@ -253,4 +249,4 @@ in `[]byte` form, is stored in a block and appended to the blockchain. ## Next {hide} -Learn about [accounts](./accounts.md) {hide} +Learn about [accounts](./03-accounts.md) {hide} diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/query-lifecycle.md b/versioned_docs/version-0.45/develop/high-level-concepts/02-query-lifecycle.md similarity index 69% rename from versioned_docs/version-0.45/develop/high-level-concepts/query-lifecycle.md rename to versioned_docs/version-0.45/develop/high-level-concepts/02-query-lifecycle.md index 55902e698..75303c44e 100644 --- a/versioned_docs/version-0.45/develop/high-level-concepts/query-lifecycle.md +++ b/versioned_docs/version-0.45/develop/high-level-concepts/02-query-lifecycle.md @@ -1,18 +1,14 @@ - - # Query Lifecycle This document describes the lifecycle of a query in a SDK application, from the user interface to application stores and back. {synopsis} ## Pre-requisite Readings -- [Transaction Lifecycle](./tx-lifecycle.md) {prereq} +- [Transaction Lifecycle](./01-tx-lifecycle.md) {prereq} ## Query Creation -A [**query**](../building-modules/messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../core/transactions.md) (view the lifecycle [here](./tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. +A [**query**](../building-modules/02-messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../advanced-concepts/01-transactions.md) (view the lifecycle [here](./01-tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. For the purpose of explaining the query lifecycle, let's say `MyQuery` is requesting a list of delegations made by a certain delegator address in the application called `simapp`. As to be expected, the [`staking`](../../x/staking/spec/README.md) module handles this query. But first, there are a few ways `MyQuery` can be created by users. @@ -34,7 +30,7 @@ simd query [moduleName] [command] --flag To provide values such as `--node` (the full-node the CLI connects to), the user can use the [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) config file to set them or provide them as flags. -The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../core/cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. +The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../advanced-concepts/06-cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. ### gRPC @@ -50,7 +46,7 @@ replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 Please see [issue #8392](https://github.com/cosmos/cosmos-sdk/issues/8392) for more info. ::: -Another interface through which users can make queries, introduced in Cosmos SDK v0.40, is [gRPC](https://grpc.io) requests to a [gRPC server](../core/grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. +Another interface through which users can make queries, introduced in Cosmos SDK v0.40, is [gRPC](https://grpc.io) requests to a [gRPC server](../advanced-concepts/08-grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. One such tool is [grpcurl](https://github.com/fullstorydev/grpcurl), and a gRPC request for `MyQuery` using this client looks like: @@ -66,7 +62,7 @@ grpcurl \ ### REST -Another interface through which users can make queries is through HTTP Requests to a [REST server](../core/grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). +Another interface through which users can make queries is through HTTP Requests to a [REST server](../advanced-concepts/08-grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). An example HTTP request for `MyQuery` looks like: @@ -82,10 +78,10 @@ The examples above show how an external user can interact with a node by queryin The first thing that is created in the execution of a CLI command is a `client.Context`. A `client.Context` is an object that stores all the data needed to process a request on the user side. In particular, a `client.Context` stores the following: -- **Codec**: The [encoder/decoder](../core/encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. +- **Codec**: The [encoder/decoder](../advanced-concepts/05-encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. - **Account Decoder**: The account decoder from the [`auth`](../..//x/auth/spec/README.md) module, which translates `[]byte`s into accounts. - **RPC Client**: The Tendermint RPC Client, or node, to which the request will be relayed to. -- **Keyring**: A [Key Manager](../basics/accounts.md#keyring) used to sign transactions and handle other operations with keys. +- **Keyring**: A [Key Manager](../high-level-concepts/03-accounts.md#keyring) used to sign transactions and handle other operations with keys. - **Output Writer**: A [Writer](https://golang.org/pkg/io/#Writer) used to output the response. - **Configurations**: The flags configured by the user for this command, including `--height`, specifying the height of the blockchain to query and `--indent`, which indicates to add an indent to the JSON response. @@ -101,7 +97,7 @@ At this point in the lifecycle, the user has created a CLI command with all of t #### Encoding -In our case (querying an address's delegations), `MyQuery` contains an [address](./accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. +In our case (querying an address's delegations), `MyQuery` contains an [address](./03-accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. Here is what the code looks like for the CLI command: @@ -113,7 +109,7 @@ The SDK leverages code generated from Protobuf services to make queries. The `st +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/staking/client/cli/query.go#L318-L342 -Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../core/node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. +Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../advanced-concepts/03-node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. Here is what the code looks like: @@ -121,17 +117,17 @@ Here is what the code looks like: ## RPC -With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../core/encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. +With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../advanced-concepts/05-encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. Read more about ABCI Clients and Tendermint RPC in the Tendermint documentation [here](https://tendermint.com/rpc). ## Application Query Handling -When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../core/baseapp.md) implements the ABCI [`Query()`](../core/baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` will relay the request to the relevant module. +When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../../develop/advanced-concepts/00-baseapp.md) implements the ABCI [`Query()`](../../develop/advanced-concepts/00-baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` will relay the request to the relevant module. -Apart from gRPC routes, `baseapp` also handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [legacy queriers](../building-modules/query-services.md#legacy-queriers). To learn more about these queries, please refer to [this guide](../core/grpc_rest.md#tendermint-rpc). +Apart from gRPC routes, `baseapp` also handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [legacy queriers](../building-modules/04-query-services.md#legacy-queriers). To learn more about these queries, please refer to [this guide](../advanced-concepts/08-grpc_rest.md#tendermint-rpc). -Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/query-services.md). +Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/04-query-services.md). Once a result is received from the querier, `baseapp` begins the process of returning a response to the user. @@ -141,7 +137,7 @@ Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci ### CLI Response -The application [`codec`](../core/encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). +The application [`codec`](../advanced-concepts/05-encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/context.go#L248-L283 @@ -149,4 +145,4 @@ And that's a wrap! The result of the query is outputted to the console by the CL ## Next {hide} -Read more about [accounts](./accounts.md). {hide} +Read more about [accounts](./03-accounts.md). {hide} diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/accounts.md b/versioned_docs/version-0.45/develop/high-level-concepts/03-accounts.md similarity index 96% rename from versioned_docs/version-0.45/develop/high-level-concepts/accounts.md rename to versioned_docs/version-0.45/develop/high-level-concepts/03-accounts.md index b8bcb76ae..6d372400f 100644 --- a/versioned_docs/version-0.45/develop/high-level-concepts/accounts.md +++ b/versioned_docs/version-0.45/develop/high-level-concepts/03-accounts.md @@ -1,7 +1,3 @@ - - # Accounts This document describes the in-built account and public key system of the Cosmos SDK. {synopsis} @@ -12,7 +8,7 @@ This document describes the in-built account and public key system of the Cosmos ## Account Definition -In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. +In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/02-messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The BIP32 allows users to create an HD wallet (as specified in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. A single seed can derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. @@ -138,7 +134,7 @@ The default implementation of `Keyring` comes from the third-party [`99designs/k A few notes on the `Keyring` methods: -- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). +- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../../develop/advanced-concepts/00-baseapp.md#antehandler). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 - `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring: diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/gas-fees.md b/versioned_docs/version-0.45/develop/high-level-concepts/04-gas-fees.md similarity index 70% rename from versioned_docs/version-0.45/develop/high-level-concepts/gas-fees.md rename to versioned_docs/version-0.45/develop/high-level-concepts/04-gas-fees.md index 0a93c1335..f319b6a6d 100644 --- a/versioned_docs/version-0.45/develop/high-level-concepts/gas-fees.md +++ b/versioned_docs/version-0.45/develop/high-level-concepts/04-gas-fees.md @@ -1,7 +1,3 @@ - - # Gas and Fees This document describes the default strategies to handle gas and fees within a Cosmos SDK application. {synopsis} @@ -15,7 +11,7 @@ This document describes the default strategies to handle gas and fees within a C In the Cosmos SDK, `gas` is a special unit that is used to track the consumption of resources during execution. `gas` is typically consumed whenever read and writes are made to the store, but it can also be consumed if expensive computation needs to be done. It serves two main purposes: - Make sure blocks are not consuming too many resources and will be finalized. This is implemented by default in the SDK via the [block gas meter](#block-gas-meter). -- Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`AnteHandler`](#antehandler). +- Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/02-messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`AnteHandler`](#antehandler). ## Gas Meter @@ -32,7 +28,7 @@ where: - `IsPastLimit()` returns `true` if the amount of gas consumed by the gas meter instance is strictly above the limit, `false` otherwise. - `IsOutOfGas()` returns `true` if the amount of gas consumed by the gas meter instance is above or equal to the limit, `false` otherwise. -The gas meter is generally held in [`ctx`](../core/context.md), and consuming gas is done with the following pattern: +The gas meter is generally held in [`ctx`](../01-tx-lifecycle.md02-context.md), and consuming gas is done with the following pattern: ```go ctx.GasMeter().ConsumeGas(amount, "description") @@ -42,17 +38,17 @@ By default, the Cosmos SDK makes use of two different gas meters, the [main gas ### Main Gas Meter -`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../core/baseapp.md#beginblock), [`DeliverTx`](../core/baseapp.md#delivertx) and [`EndBlock`](../core/baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. +`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock), [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx) and [`EndBlock`](../../develop/advanced-concepts/00-baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. -Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) or [`Msg` service](../building-modules/msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../core/store.md#gaskv-store). +Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) or [`Msg` service](../building-modules/03-msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../01-tx-lifecycle.md04-store.md#gaskv-store). ### Block Gas Meter -`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../core/baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default Cosmos SDK applications use the default consensus parameters provided by Tendermint: +`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default Cosmos SDK applications use the default consensus parameters provided by Tendermint: +++ https://github.com/tendermint/tendermint/blob/v0.34.0-rc6/types/params.go#L34-L41 -When a new [transaction](../core/transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: +When a new [transaction](../01-tx-lifecycle.md01-transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: ```go ctx.BlockGasMeter().ConsumeGas( @@ -77,13 +73,13 @@ The `anteHandler` is not implemented in the core SDK but in a module. This gives +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/tx_msg.go#L49-L57 This enables developers to play with various types for the transaction of their application. In the default `auth` module, the default transaction type is `Tx`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L12-L25 -- Verify signatures for each [`message`](../building-modules/messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. +- Verify signatures for each [`message`](../building-modules/02-messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. - During `CheckTx`, verify that the gas prices provided with the transaction is greater than the local `min-gas-prices` (as a reminder, gas-prices can be deducted from the following equation: `fees = gas * gas-prices`). `min-gas-prices` is a parameter local to each full-node and used during `CheckTx` to discard transactions that do not provide a minimum amount of fees. This ensure that the mempool cannot be spammed with garbage transactions. - Verify that the sender of the transaction has enough funds to cover for the `fees`. When the end-user generates a transaction, they must indicate 2 of the 3 following parameters (the third one being implicit): `fees`, `gas` and `gas-prices`. This signals how much they are willing to pay for nodes to execute their transaction. The provided `gas` value is stored in a parameter called `GasWanted` for later use. - Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is extremely important**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx` is set to `newCtx` after `anteHandler` is run, and the `anteHandler` is run each time `DeliverTx` is called). -As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../core/baseapp.md#delivertx) returns. +As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx) returns. ## Next {hide} -Learn about [baseapp](../core/baseapp.md) {hide} +Learn about [baseapp](../../develop/advanced-concepts/00-baseapp.md) {hide} diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/README.md b/versioned_docs/version-0.45/develop/high-level-concepts/README.md deleted file mode 100644 index 03934dcd5..000000000 --- a/versioned_docs/version-0.45/develop/high-level-concepts/README.md +++ /dev/null @@ -1,17 +0,0 @@ - - -# Basics - -This repository contains reference documentation on the basic concepts of the Cosmos SDK. - -1. [Anatomy of an SDK Application](./app-anatomy.md) -2. [Lifecycle of a transaction](./tx-lifecycle.md) -3. [Lifecycle of a query](./query-lifecycle.md) -4. [Accounts](./accounts.md) -5. [Gas and Fees](./gas-fees.md) - -After reading the basics, head on to the [Core Reference](../core/README.md) for more advanced material. diff --git a/versioned_docs/version-0.45/develop/high-level-concepts/_category_.json b/versioned_docs/version-0.45/develop/high-level-concepts/_category_.json new file mode 100644 index 000000000..2c4105ee6 --- /dev/null +++ b/versioned_docs/version-0.45/develop/high-level-concepts/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "High Level Concepts", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/develop/intro/README.md b/versioned_docs/version-0.45/develop/intro/README.md deleted file mode 100644 index 1b3365ba2..000000000 --- a/versioned_docs/version-0.45/develop/intro/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - -# Introduction - -This folder contains introduction material on the Cosmos SDK. - -1. [Overview](./overview.md) -2. [Application-Specific Blockchains](./why-app-specific.md) -3. [Architecture of an SDK Application](./sdk-app-architecture.md) -4. [Cosmos SDK Design Overview](./sdk-design.md) - -After reading the introduction material, head over to the [basics](../basics/README.md) to learn more. diff --git a/versioned_docs/version-0.45/develop/intro/overview.md b/versioned_docs/version-0.45/develop/intro/overview.md index 4d0212719..4040cdd99 100644 --- a/versioned_docs/version-0.45/develop/intro/overview.md +++ b/versioned_docs/version-0.45/develop/intro/overview.md @@ -1,14 +1,10 @@ - - # High-level Overview ## What is the SDK? The [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk) is an open-source framework for building multi-asset public Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as permissioned Proof-Of-Authority (PoA) blockchains. Blockchains built with the Cosmos SDK are generally referred to as **application-specific blockchains**. -The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the SDK as the npm-like framework to build secure blockchain applications on top of [Tendermint](https://github.com/tendermint/tendermint). SDK-based blockchains are built out of composable [modules](../building-modules/intro.md), most of which are open source and readily available for any developers to use. Anyone can create a module for the Cosmos-SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system, which allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [this section](../core/ocap.md). +The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the SDK as the npm-like framework to build secure blockchain applications on top of [Tendermint](https://github.com/tendermint/tendermint). SDK-based blockchains are built out of composable [modules](../building-modules/intro.md), most of which are open source and readily available for any developers to use. Anyone can create a module for the Cosmos-SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system, which allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [this section](../01-tx-lifecycle.mdocap.md). ## What are Application-Specific Blockchains? diff --git a/versioned_docs/version-0.45/develop/intro/sdk-app-architecture.md b/versioned_docs/version-0.45/develop/intro/sdk-app-architecture.md index 1b3e40e94..803756d6c 100644 --- a/versioned_docs/version-0.45/develop/intro/sdk-app-architecture.md +++ b/versioned_docs/version-0.45/develop/intro/sdk-app-architecture.md @@ -1,7 +1,3 @@ - - # Blockchain Architecture ## State machine @@ -84,8 +80,8 @@ Note that **Tendermint only handles transaction bytes**. It has no knowledge of Here are the most important messages of the ABCI: -- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. -- `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service](../building-modules/msg-services.md) RPC for each message in the transaction. +- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +- `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service](../building-modules/03-msg-services.md) RPC for each message in the transaction. - `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transaction or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/v0.34/spec/abci/abci.html#overview). diff --git a/versioned_docs/version-0.45/develop/intro/sdk-design.md b/versioned_docs/version-0.45/develop/intro/sdk-design.md index 5c8c26965..a598b8ee8 100644 --- a/versioned_docs/version-0.45/develop/intro/sdk-design.md +++ b/versioned_docs/version-0.45/develop/intro/sdk-design.md @@ -1,10 +1,6 @@ - - # Main Components of the Cosmos SDK -The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of Tendermint. At its core, the SDK is a boilerplate implementation of the [ABCI](./sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../core/store.md#multistore) to persist data and a [`router`](../core/baseapp.md#routing) to handle transactions. +The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of Tendermint. At its core, the SDK is a boilerplate implementation of the [ABCI](./sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../01-tx-lifecycle.md04-store.md#multistore) to persist data and a [`router`](../../develop/advanced-concepts/00-baseapp.md#routing) to handle transactions. Here is a simplified view of how transactions are handled by an application built on top of the Cosmos SDK when transferred from Tendermint via `DeliverTx`: @@ -15,19 +11,19 @@ Here is a simplified view of how transactions are handled by an application buil ## `baseapp` -`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../basics/app-anatomy.md#core-application-file). See an example of this from the SDK application tutorial: +`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../high-level-concepts/app-anatomy.md#core-application-file). See an example of this from the SDK application tutorial: +++ https://github.com/cosmos/sdk-tutorials/blob/c6754a1e313eb1ed973c5c91dcc606f2fd288811/app.go#L72-L92 The goal of `baseapp` is to provide a secure interface between the store and the extensible state machine while defining as little about the state machine as possible (staying true to the ABCI). -For more on `baseapp`, please click [here](../core/baseapp.md). +For more on `baseapp`, please click [here](../../develop/advanced-concepts/00-baseapp.md). ## Multistore -The Cosmos SDK provides a [`multistore`](../core/store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../core/store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../core/encoding.md) before being stored. +The Cosmos SDK provides a [`multistore`](../01-tx-lifecycle.md04-store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../01-tx-lifecycle.md04-store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../advanced-concepts/05-encoding.md) before being stored. -The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../core/store.md#multistore) +The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../advanced-concepts/04-store.md#multistore) ## Modules @@ -80,7 +76,7 @@ Here is a simplified view of how a transaction is processed by the application o v ``` -Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../core/ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. +Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../advanced-concepts/ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. SDK modules are defined in the `x/` folder of the SDK. Some core modules include: @@ -92,4 +88,4 @@ In addition to the already existing modules in `x/`, that anyone can use in thei ## Next {hide} -Learn more about the [anatomy of an SDK application](../basics/app-anatomy.md) {hide} +Learn more about the [anatomy of an SDK application](../high-level-concepts/app-anatomy.md) {hide} diff --git a/versioned_docs/version-0.45/develop/intro/why-app-specific.md b/versioned_docs/version-0.45/develop/intro/why-app-specific.md index f7c5f72d7..f9d53c232 100644 --- a/versioned_docs/version-0.45/develop/intro/why-app-specific.md +++ b/versioned_docs/version-0.45/develop/intro/why-app-specific.md @@ -1,7 +1,3 @@ - - # Application-Specific Blockchains This document explains what application-specific blockchains are, and why developers would want to build one as opposed to writing Smart Contracts. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/_category_.json b/versioned_docs/version-0.45/integrate/_category_.json new file mode 100644 index 000000000..b860342f4 --- /dev/null +++ b/versioned_docs/version-0.45/integrate/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Integrate", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/integrate/architecture/adr-038-state-listening.md b/versioned_docs/version-0.45/integrate/architecture/adr-038-state-listening.md index 74f92d2f6..12d0bdb8b 100644 --- a/versioned_docs/version-0.45/integrate/architecture/adr-038-state-listening.md +++ b/versioned_docs/version-0.45/integrate/architecture/adr-038-state-listening.md @@ -19,7 +19,7 @@ This ADR defines a set of changes to enable listening to state changes of indivi ## Context -Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/02-messages-and-queries.md#queries) which proceed either through Tendermint and the ABCI, or through the gRPC server. In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. diff --git a/versioned_docs/version-0.45/integrate/architecture/adr-040-storage-and-smt-state-commitments.md b/versioned_docs/version-0.45/integrate/architecture/adr-040-storage-and-smt-state-commitments.md index 115723576..4189922cc 100644 --- a/versioned_docs/version-0.45/integrate/architecture/adr-040-storage-and-smt-state-commitments.md +++ b/versioned_docs/version-0.45/integrate/architecture/adr-040-storage-and-smt-state-commitments.md @@ -23,7 +23,7 @@ In the current design, IAVL is used for both data storage and as a Merkle Tree f + Each edge traversal requires a DB query. + Creating snapshots is [expensive](https://github.com/cosmos/cosmos-sdk/issues/7215#issuecomment-684804950). It takes about 30 seconds to export less than 100 MB of state (as of March 2020). + Updates in IAVL may trigger tree reorganization and possible O(log(n)) hashes re-computation, which can become a CPU bottleneck. -+ The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/node.md ++ The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/03-node.md ). Moreover, the IAVL project lacks support and a maintainer and we already see better and well-established alternatives. Instead of optimizing the IAVL, we are looking into other solutions for both storage and state commitments. diff --git a/versioned_docs/version-0.45/integrate/building-modules/intro.md b/versioned_docs/version-0.45/integrate/building-modules/00-intro.md similarity index 77% rename from versioned_docs/version-0.45/integrate/building-modules/intro.md rename to versioned_docs/version-0.45/integrate/building-modules/00-intro.md index b486176bc..b47984e12 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/intro.md +++ b/versioned_docs/version-0.45/integrate/building-modules/00-intro.md @@ -1,23 +1,19 @@ - - # Introduction to SDK Modules Modules define most of the logic of SDK applications. Developers compose modules together using the Cosmos SDK to build their custom application-specific blockchains. This document outlines the basic concepts behind SDK modules and how to approach module management. {synopsis} ## Pre-requisite Readings -- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} -- [Lifecycle of an SDK transaction](../basics/tx-lifecycle.md) {prereq} +- [Anatomy of an SDK application](../high-level-concepts/app-anatomy.md) {prereq} +- [Lifecycle of an SDK transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Role of Modules in an SDK Application -The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../core/baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../core/store.md#multistore) to persist state, a [server](../core/node.md) to form a full-node and [interfaces](./module-interfaces.md) to handle queries. +The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../../develop/advanced-concepts/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../advanced-concepts/04-store.md#multistore) to persist state, a [server](../advanced-concepts/03-node.md) to form a full-node and [interfaces](./09-module-interfaces.md) to handle queries. On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source SDK modules, making it increasingly easier to build complex blockchain applications. -SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../core/store.md), as well as a subset of [message types](./messages-and-queries.md#messages). These messages are routed by one of the main components of SDK core, [`BaseApp`](../core/baseapp.md), to a module Protobuf [`Msg` service](./msg-services.md) that defines them. +SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../advanced-concepts/04-store.md), as well as a subset of [message types](./02-messages-and-queries.md#messages). These messages are routed by one of the main components of SDK core, [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md), to a module Protobuf [`Msg` service](./03-msg-services.md) that defines them. ``` + @@ -70,23 +66,23 @@ As a result of this architecture, building an SDK application usually revolves a While there are no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them: -- **Composability**: SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./keeper.md). -- **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. -- **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. +- **Composability**: SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./06-keeper.md). +- **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../advanced-concepts/ocap.md) of the Cosmos SDK. +- **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./06-keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. ## Main Components of SDK Modules Modules are by convention defined in the `./x/` subfolder (e.g. the `bank` module will be defined in the `./x/bank` folder). They generally share the same core components: -- A [`keeper`](./keeper.md), used to access the module's store(s) and update the state. -- A [`Msg` service](./messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../core/baseapp.md#message-routing) and trigger state-transitions. -- A [query service](./query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../core/baseapp.md#query-routing). +- A [`keeper`](./06-keeper.md), used to access the module's store(s) and update the state. +- A [`Msg` service](./02-messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#message-routing) and trigger state-transitions. +- A [query service](./04-query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#query-routing). - Interfaces, for end users to query the subset of the state defined by the module and create `message`s of the custom types defined in the module. -In addition to these components, modules implement the `AppModule` interface in order to be managed by the [`module manager`](./module-manager.md). +In addition to these components, modules implement the `AppModule` interface in order to be managed by the [`module manager`](./01-module-manager.md). -Please refer to the [structure document](./structure.md) to learn about the recommended structure of a module's directory. +Please refer to the [structure document](./11-structure.md) to learn about the recommended structure of a module's directory. ## Next {hide} -Read more on the [`AppModule` interface and the `module manager`](./module-manager.md) {hide} +Read more on the [`AppModule` interface and the `module manager`](./01-module-manager.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/module-manager.md b/versioned_docs/version-0.45/integrate/building-modules/01-module-manager.md similarity index 63% rename from versioned_docs/version-0.45/integrate/building-modules/module-manager.md rename to versioned_docs/version-0.45/integrate/building-modules/01-module-manager.md index 334d252e6..9d66fd5fa 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/module-manager.md +++ b/versioned_docs/version-0.45/integrate/building-modules/01-module-manager.md @@ -1,10 +1,6 @@ - - # Module Manager -Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../core/baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#begingblocker-and-endblocker). {synopsis} +Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../../develop/advanced-concepts/00-baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../high-level-concepts/app-anatomy.md#begingblocker-and-endblocker). {synopsis} ## Pre-requisite Readings @@ -18,9 +14,9 @@ Application module interfaces exist to facilitate the composition of modules tog - [`AppModule`](#appmodule) for inter-dependent module functionalities (except genesis-related functionalities). - [`AppModuleGenesis`](#appmodulegenesis) for inter-dependent genesis-related module functionalities. -The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../basics/app-anatomy.md#core-application-file). +The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../high-level-concepts/app-anatomy.md#core-application-file). -The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interract with other modules, typically through [`keeper`s](./keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. +The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interract with other modules, typically through [`keeper`s](./06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. Lastly the interface for genesis functionality `AppModuleGenesis` is separated out from full module functionality `AppModule` so that modules which are only used for genesis can take advantage of the `Module` patterns without having to define many placeholder functions. @@ -36,12 +32,12 @@ Let us go through the methods: - `Name()`: Returns the name of the module as a `string`. - `RegisterLegacyAminoCodec(*codec.LegacyAmino)`: Registers the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`. - `RegisterInterfaces(codectypes.InterfaceRegistry)`: Registers a module's interface types and their concrete implementations as `proto.Message`. -- `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. -- `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./genesis.md#validategenesis) function defined by the module developer. -- `RegisterRESTRoutes(client.Context, *mux.Router)`: Registers the REST routes for the module. These routes will be used to map REST request to the module in order to process them. See [gRPC and REST](../core/grpc_rest.md) for more. +- `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./08-genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. +- `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./08-genesis.md#validategenesis) function defined by the module developer. +- `RegisterRESTRoutes(client.Context, *mux.Router)`: Registers the REST routes for the module. These routes will be used to map REST request to the module in order to process them. See [gRPC and REST](../advanced-concepts/08-grpc_rest.md) for more. - `RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)`: Registers gRPC routes for the module. -- `GetTxCmd()`: Returns the root [`Tx` command](./module-interfaces.md#tx) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](./messages-and-queries.md#queries) defined in the module. -- `GetQueryCmd()`: Return the root [`query` command](./module-interfaces.md#query) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. +- `GetTxCmd()`: Returns the root [`Tx` command](./09-module-interfaces.md#tx) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](./02-messages-and-queries.md#queries) defined in the module. +- `GetQueryCmd()`: Return the root [`query` command](./09-module-interfaces.md#query) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. All the `AppModuleBasic` of an application are managed by the [`BasicManager`](#basicmanager). @@ -68,10 +64,10 @@ The `AppModule` interface defines the inter-dependent methods that modules need Let us go through the methods of `AppModule`: -- `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](./invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](./invariants.md#registry) triggers appropriate logic (most often the chain will be halted). -- `Route()`: Returns the route for [`message`s](./messages-and-queries.md#messages) to be routed to the module by [`BaseApp`](../core/baseapp.md#message-routing). -- `QuerierRoute()` (deprecated): Returns the name of the module's query route, for [`queries`](./messages-and-queries.md#queries) to be routes to the module by [`BaseApp`](../core/baseapp.md#query-routing). -- `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. +- `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](./07-invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](./07-invariants.md#registry) triggers appropriate logic (most often the chain will be halted). +- `Route()`: Returns the route for [`message`s](./02-messages-and-queries.md#messages) to be routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#message-routing). +- `QuerierRoute()` (deprecated): Returns the name of the module's query route, for [`queries`](./02-messages-and-queries.md#queries) to be routes to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#query-routing). +- `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./04-query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. - `RegisterServices(Configurator)`: Allows a module to register services. - `BeginBlock(sdk.Context, abci.RequestBeginBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. Implement empty if no logic needs to be triggered at the beginning of each block for this module. - `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the end of each block for this module. @@ -80,7 +76,7 @@ Let us go through the methods of `AppModule`: Typically, the various application module interfaces are implemented in a file called `module.go`, located in the module's folder (e.g. `./x/module/module.go`). -Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./keeper.md) as a parameter. +Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./06-keeper.md) as a parameter. ```go // example @@ -110,15 +106,15 @@ The `BasicManager` is a structure that lists all the `AppModuleBasic` of an appl It implements the following methods: -- `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../basics/app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/master/app/app.go#L59-L74) to see an example). -- `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../core/encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../basics/app-anatomy.md#constructor). +- `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../high-level-concepts/app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/master/app/app.go#L59-L74) to see an example). +- `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../core/05-encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../high-level-concepts/app-anatomy.md#constructor). - `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModuleBasic`. -- `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./genesis.md#defaultgenesis) function of each module. It is used to construct a default genesis file for the application. -- `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./genesis.md#validategenesis) function of each module. -- `RegisterRESTRoutes(ctx client.Context, rtr *mux.Router)`: Registers REST routes for modules by calling the [`RegisterRESTRoutes`](./module-interfaces.md#register-routes) function of each module. This function is usually called function from the `main.go` function of the [application's command-line interface](../core/cli.md). +- `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It is used to construct a default genesis file for the application. +- `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of each module. +- `RegisterRESTRoutes(ctx client.Context, rtr *mux.Router)`: Registers REST routes for modules by calling the [`RegisterRESTRoutes`](./09-module-interfaces.md#register-routes) function of each module. This function is usually called function from the `main.go` function of the [application's command-line interface](../core/06-cli.md). - `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules. -- `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../core/cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/cli.md). -- `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../core/cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/cli.md). +- `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../core/06-cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/06-cli.md). +- `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../core/06-cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/06-cli.md). ### `Manager` @@ -128,18 +124,18 @@ The `Manager` is a structure that holds all the `AppModule` of an application, a The module manager is used throughout the application whenever an action on a collection of modules is required. It implements the following methods: -- `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./invariants.md) of each module. -- `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./messages-and-queries.md#messages) and [`querier`](./query-services.md#legacy-queriers) routes. +- `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +- `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +- `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +- `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +- `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./07-invariants.md) of each module. +- `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./02-messages-and-queries.md#messages) and [`querier`](./04-query-services.md#legacy-queriers) routes. - `RegisterServices(cfg Configurator)`: Registers all module services. -- `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. -- `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. -- `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../core/baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderBeginBlockers`. It creates a child [context](../core/context.md) with an event manager to aggregate [events](../core/events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. -- `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../core/baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderEndBlockers`. It creates a child [context](../core/context.md) with an event manager to aggregate [events](../core/events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). +- `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. +- `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. +- `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderBeginBlockers`. It creates a child [context](../core/02-context.md) with an event manager to aggregate [events](../core/07-events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. +- `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderEndBlockers`. It creates a child [context](../core/02-context.md) with an event manager to aggregate [events](../core/07-events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). Here's an example of a concrete integration within an application: @@ -147,4 +143,4 @@ Here's an example of a concrete integration within an application: ## Next {hide} -Learn more about [`message`s and `queries`](./messages-and-queries.md) {hide} +Learn more about [`message`s and `queries`](./02-messages-and-queries.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/messages-and-queries.md b/versioned_docs/version-0.45/integrate/building-modules/02-messages-and-queries.md similarity index 72% rename from versioned_docs/version-0.45/integrate/building-modules/messages-and-queries.md rename to versioned_docs/version-0.45/integrate/building-modules/02-messages-and-queries.md index 6b5db1a72..91a695e0b 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/messages-and-queries.md +++ b/versioned_docs/version-0.45/integrate/building-modules/02-messages-and-queries.md @@ -1,7 +1,3 @@ - - # Messages and Queries `Msg`s and `Queries` are the two primary objects handled by modules. Most of the core components defined in a module, like `Msg` services, `keeper`s and `Query` services, exist to process `message`s and `queries`. {synopsis} @@ -12,13 +8,13 @@ order: 3 ## Messages -`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../core/transactions.md), which may contain one or more of them. +`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../advanced-concepts/01-transactions.md), which may contain one or more of them. -When a transaction is relayed from the underlying consensus engine to the SDK application, it is first decoded by [`BaseApp`](../core/baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](./msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../basics/tx-lifecycle.md). +When a transaction is relayed from the underlying consensus engine to the SDK application, it is first decoded by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](./03-msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../high-level-concepts/01-tx-lifecycle.md). ### `Msg` Services -Starting from v0.40, defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../core/encoding.md#faq)). It must have an RPC service method defined for each message in the module. +Starting from v0.40, defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../advanced-concepts/05-encoding.md#faq)). It must have an RPC service method defined for each message in the module. See an example of a `Msg` service definition from `x/bank` module: @@ -34,10 +30,10 @@ Each `Msg` service method must have exactly one argument, which must implement t Cosmos SDK uses Protobuf definitions to generate client and server code: -* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](./msg-services.md) documentation. +* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](./03-msg-services.md) documentation. * Structures are generated for all RPC request and response types. -A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./module-manager.md#appmodule). +A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). In order for clients (CLI and grpc-gateway) to have these URLs registered, the SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](module-manager.md#appmodulebasic) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument. @@ -47,15 +43,15 @@ The following way of defining messages is deprecated and using [`Msg` services]( Amino `LegacyMsg`s can be defined as protobuf messages. The messages definition usually includes a list of parameters needed to process the message that will be provided by end-users when they want to create a new transaction containing said message. -A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](./module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: +A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](./09-module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: +++ https://github.com/cosmos/cosmos-sdk/blob/4a1b2fba43b1052ca162b3a1e0b6db6db9c26656/types/tx_msg.go#L10-L33 It extends `proto.Message` and contains the following methods: - `Route() string`: Name of the route for this message. Typically all `message`s in a module have the same route, which is most often the module's name. -- `Type() string`: Type of the message, used primarly in [events](../core/events.md). This should return a message-specific `string`, typically the denomination of the message itself. -- [`ValidateBasic() error`](../basics/tx-lifecycle.md#ValidateBasic). +- `Type() string`: Type of the message, used primarly in [events](../advanced-concepts/07-events.md). This should return a message-specific `string`, typically the denomination of the message itself. +- [`ValidateBasic() error`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic). - `GetSignBytes() []byte`: Return the canonical byte representation of the message. Used to generate a signature. - `GetSigners() []AccAddress`: Return the list of signers. The SDK will make sure that each `message` contained in a transaction is signed by all the signers listed in the list returned by this method. @@ -65,7 +61,7 @@ See an example implementation of a `message` from the `gov` module: ## Queries -A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `queryrouter` so that it can be processed by the module's query service (./query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../basics/query-lifecycle.md). +A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `queryrouter` so that it can be processed by the module's query service (./04-query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../high-level-concepts/query-lifecycle.md). ### gRPC Queries @@ -77,7 +73,7 @@ Here's an example of such a `Query` service definition: As `proto.Message`s, generated `Response` types implement by default `String()` method of [`fmt.Stringer`](https://golang.org/pkg/fmt/#Stringer). -A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](./module-manager.md#appmodule). +A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). ### Legacy Queries @@ -89,15 +85,15 @@ queryCategory/queryRoute/queryType/arg1/arg2/... where: -- `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../core/baseapp.md#query). -- `queryRoute` is used by `BaseApp`'s [`queryRouter`](../core/baseapp.md#query-routing) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. -- `queryType` is used by the module's [`querier`](./query-services.md#legacy-queriers) to map the `query` to the appropriate `querier function` within the module. +- `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). +- `queryRoute` is used by `BaseApp`'s [`queryRouter`](../../develop/advanced-concepts/00-baseapp.md#query-routing) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. +- `queryType` is used by the module's [`querier`](./04-query-services.md#legacy-queriers) to map the `query` to the appropriate `querier function` within the module. - `args` are the actual arguments needed to process the `query`. They are filled out by the end-user. Note that for bigger queries, you might prefer passing arguments in the `Data` field of the request `req` instead of the `path`. -The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](./module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: +The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](./09-module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: -- A [`querier`](./query-services.md#legacy-queriers), to process the `query` once it has been [routed to the module](../core/baseapp.md#query-routing). -- [Query commands](./module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. +- A [`querier`](./04-query-services.md#legacy-queriers), to process the `query` once it has been [routed to the module](../../develop/advanced-concepts/00-baseapp.md#query-routing). +- [Query commands](./09-module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. - `query` return types. Typically defined in a file `types/querier.go`, they specify the result type of each of the module's `queries`. These custom types must implement the `String()` method of [`fmt.Stringer`](https://golang.org/pkg/fmt/#Stringer). ### Store Queries @@ -106,10 +102,10 @@ Store queries query directly for store keys. They use `clientCtx.QueryABCI(req a See following examples: -+++ https://github.com/cosmos/cosmos-sdk/blob/080fcf1df25ccdf97f3029b6b6f83caaf5a235e4/x/ibc/core/client/query.go#L36-L46 ++++ https://github.com/cosmos/cosmos-sdk/blob/080fcf1df25ccdf97f3029b6b6f83caaf5a235e4/x/ibc/advanced-concepts/client/query.go#L36-L46 +++ https://github.com/cosmos/cosmos-sdk/blob/080fcf1df25ccdf97f3029b6b6f83caaf5a235e4/baseapp/abci.go#L722-L749 ## Next {hide} -Learn about [`Msg` services](./msg-services.md) {hide} +Learn about [`Msg` services](./03-msg-services.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/msg-services.md b/versioned_docs/version-0.45/integrate/building-modules/03-msg-services.md similarity index 71% rename from versioned_docs/version-0.45/integrate/building-modules/msg-services.md rename to versioned_docs/version-0.45/integrate/building-modules/03-msg-services.md index de7107b92..7bf77b70a 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/msg-services.md +++ b/versioned_docs/version-0.45/integrate/building-modules/03-msg-services.md @@ -1,15 +1,11 @@ - - # `Msg` Services -A Protobuf `Msg` service processes [messages](./messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../core/baseapp.md#delivertx). {synopsis} +A Protobuf `Msg` service processes [messages](./02-messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx). {synopsis} ## Pre-requisite Readings -- [Module Manager](./module-manager.md) {prereq} -- [Messages and Queries](./messages-and-queries.md) {prereq} +- [Module Manager](./01-module-manager.md) {prereq} +- [Messages and Queries](./02-messages-and-queries.md) {prereq} ## Implementation of a module `Msg` service @@ -33,7 +29,7 @@ When possible, the existing module's [`Keeper`](keeper.md) should implement `Msg ### Validation -Before a `msgServer` method is executed, the message's [`ValidateBasic()`](../basics/tx-lifecycle.md#ValidateBasic) method has already been called. Since `msg.ValidateBasic()` performs only the most basic checks, this stage must perform all other validation (both *stateful* and *stateless*) to make sure the `message` is valid. Checks performed in the `msgServer` method can be more expensive and the signer is charged gas for these operations. +Before a `msgServer` method is executed, the message's [`ValidateBasic()`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) method has already been called. Since `msg.ValidateBasic()` performs only the most basic checks, this stage must perform all other validation (both *stateful* and *stateless*) to make sure the `message` is valid. Checks performed in the `msgServer` method can be more expensive and the signer is charged gas for these operations. For example, a `msgServer` method for a `transfer` message might check that the sending account has enough funds to actually perform the transfer. It is recommended to implement all validation checks in a separate function that passes state values as arguments. This implementation simplifies testing. As expected, expensive validation functions charge additional gas. Example: @@ -50,11 +46,11 @@ ValidateMsgA(msg MsgA, now Time, gm GasMeter) error { ### State Transition -After the validation is successful, the `msgServer` method uses the [`keeper`](./keeper.md) functions to access the state and perform a state transition. +After the validation is successful, the `msgServer` method uses the [`keeper`](./06-keeper.md) functions to access the state and perform a state transition. ### Events -Before returning, `msgServer` methods generally emit one or more [events](../core/events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: +Before returning, `msgServer` methods generally emit one or more [events](../advanced-concepts/07-events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: ``` ctx.EventManager().EmitTypedEvent( @@ -73,7 +69,7 @@ ctx.EventManager().EmitEvent( ) ``` -These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../core/events.md) to learn more about events. +These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../advanced-concepts/07-events.md) to learn more about events. The invoked `msgServer` method returns a `proto.Message` response and an `error`. These return values are then wrapped into an `*sdk.Result` or an `error` using `sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error)`: @@ -99,12 +95,12 @@ Here is the typical structure of a `handler` function: Let us break it down: -- The [`LegacyMsg`](./messages-and-queries.md#messages) is the actual object being processed. -- The [`Context`](../core/context.md) contains all the necessary information needed to process the `msg`, as well as a branch of the latest state. If the `msg` is successfully processed, the branched version of the state contained in the `ctx` will be written to the main state (branch). -- The `*Result` returned to `BaseApp` contains (among other things) information on the execution of the `handler` and [events](../core/events.md). +- The [`LegacyMsg`](./02-messages-and-queries.md#messages) is the actual object being processed. +- The [`Context`](../advanced-concepts/02-context.md) contains all the necessary information needed to process the `msg`, as well as a branch of the latest state. If the `msg` is successfully processed, the branched version of the state contained in the `ctx` will be written to the main state (branch). +- The `*Result` returned to `BaseApp` contains (among other things) information on the execution of the `handler` and [events](../advanced-concepts/07-events.md). -Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The [module manager](./module-manager.md) is used to add the module's `handler`s to the -[application's `router`](../core/baseapp.md#message-routing) via the `Route()` method. Typically, +Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The [module manager](./01-module-manager.md) is used to add the module's `handler`s to the +[application's `router`](../../develop/advanced-concepts/00-baseapp.md#message-routing) via the `Route()` method. Typically, the manager's `Route()` method simply constructs a Route that calls a `NewHandler()` method defined in `handler.go`. +++ https://github.com/cosmos/cosmos-sdk/blob/228728cce2af8d494c8b4e996d011492139b04ab/x/gov/module.go#L143-L146 @@ -123,7 +119,7 @@ In this regard, `handler`s functions need to be implemented for each module `Leg ## Telemetry -New [telemetry metrics](../core/telemetry.md) can be created from `msgServer` methods when handling messages. +New [telemetry metrics](../advanced-concepts/11-telemetry.md) can be created from `msgServer` methods when handling messages. This is an example from the `x/auth/vesting` module: @@ -131,4 +127,4 @@ This is an example from the `x/auth/vesting` module: ## Next {hide} -Learn about [query services](./query-services.md) {hide} +Learn about [query services](./04-query-services.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/query-services.md b/versioned_docs/version-0.45/integrate/building-modules/04-query-services.md similarity index 65% rename from versioned_docs/version-0.45/integrate/building-modules/query-services.md rename to versioned_docs/version-0.45/integrate/building-modules/04-query-services.md index 4113e099e..189c1b4b5 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/query-services.md +++ b/versioned_docs/version-0.45/integrate/building-modules/04-query-services.md @@ -1,15 +1,11 @@ - - # Query Services -A Protobuf Query service processes [`queries`](./messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../core/baseapp.md#query). {synopsis} +A Protobuf Query service processes [`queries`](./02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). {synopsis} ## Pre-requisite Readings -- [Module Manager](./module-manager.md) {prereq} -- [Messages and Queries](./messages-and-queries.md) {prereq} +- [Module Manager](./01-module-manager.md) {prereq} +- [Messages and Queries](./02-messages-and-queries.md) {prereq} ## `Querier` type @@ -19,10 +15,10 @@ The `querier` type defined in the Cosmos SDK will be deprecated in favor of [gRP Let us break it down: -- The `path` is an array of `string`s that contains the type of the query, and that can also contain `query` arguments. See [`queries`](./messages-and-queries.md#queries) for more information. +- The `path` is an array of `string`s that contains the type of the query, and that can also contain `query` arguments. See [`queries`](./02-messages-and-queries.md#queries) for more information. - The `req` itself is primarily used to retrieve arguments if they are too large to fit in the `path`. This is done using the `Data` field of `req`. -- The [`Context`](../core/context.md) contains all the necessary information needed to process the `query`, as well as a branch of the latest state. It is primarily used by the [`keeper`](./keeper.md) to access the state. -- The result `res` returned to `BaseApp`, marshalled using the application's [`codec`](../core/encoding.md). +- The [`Context`](../advanced-concepts/02-context.md) contains all the necessary information needed to process the `query`, as well as a branch of the latest state. It is primarily used by the [`keeper`](./06-keeper.md) to access the state. +- The result `res` returned to `BaseApp`, marshalled using the application's [`codec`](../advanced-concepts/05-encoding.md). ## Implementation of a module query service @@ -47,7 +43,7 @@ Here's an example implementation for the bank module: ### Legacy Queriers -Module legacy `querier`s are typically implemented in a `./keeper/querier.go` file inside the module's folder. The [module manager](./module-manager.md) is used to add the module's `querier`s to the [application's `queryRouter`](../core/baseapp.md#query-routing) via the `NewQuerier()` method. Typically, the manager's `NewQuerier()` method simply calls a `NewQuerier()` method defined in `keeper/querier.go`, which looks like the following: +Module legacy `querier`s are typically implemented in a `./keeper/querier.go` file inside the module's folder. The [module manager](./01-module-manager.md) is used to add the module's `querier`s to the [application's `queryRouter`](../../develop/advanced-concepts/00-baseapp.md#query-routing) via the `NewQuerier()` method. Typically, the manager's `NewQuerier()` method simply calls a `NewQuerier()` method defined in `keeper/querier.go`, which looks like the following: ```go func NewQuerier(keeper Keeper) sdk.Querier { @@ -66,9 +62,9 @@ func NewQuerier(keeper Keeper) sdk.Querier { } ``` -This simple switch returns a `querier` function specific to the type of the received `query`. At this point of the [query lifecycle](../basics/query-lifecycle.md), the first element of the `path` (`path[0]`) contains the type of the query. The following elements are either empty or contain arguments needed to process the query. +This simple switch returns a `querier` function specific to the type of the received `query`. At this point of the [query lifecycle](../high-level-concepts/query-lifecycle.md), the first element of the `path` (`path[0]`) contains the type of the query. The following elements are either empty or contain arguments needed to process the query. -The `querier` functions themselves are pretty straighforward. They generally fetch a value or values from the state using the [`keeper`](./keeper.md). Then, they marshall the value(s) using the [`codec`](../core/encoding.md) and return the `[]byte` obtained as result. +The `querier` functions themselves are pretty straighforward. They generally fetch a value or values from the state using the [`keeper`](./06-keeper.md). Then, they marshall the value(s) using the [`codec`](../advanced-concepts/05-encoding.md) and return the `[]byte` obtained as result. For a deeper look at `querier`s, see this [example implementation of a `querier` function](https://github.com/cosmos/cosmos-sdk/blob/7f59723d889b69ca19966167f0b3a7fec7a39e53/x/gov/keeper/querier.go) from the bank module. diff --git a/versioned_docs/version-0.45/integrate/building-modules/beginblock-endblock.md b/versioned_docs/version-0.45/integrate/building-modules/05-beginblock-endblock.md similarity index 63% rename from versioned_docs/version-0.45/integrate/building-modules/beginblock-endblock.md rename to versioned_docs/version-0.45/integrate/building-modules/05-beginblock-endblock.md index 2814c0ae9..233ada4cf 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/beginblock-endblock.md +++ b/versioned_docs/version-0.45/integrate/building-modules/05-beginblock-endblock.md @@ -1,30 +1,26 @@ - - # BeginBlocker and EndBlocker -`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../core/baseapp.md#beginblock) and [`EndBlock`](../core/baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. {synopsis} +`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and [`EndBlock`](../../develop/advanced-concepts/00-baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. {synopsis} ## Pre-requisite Readings -- [Module Manager](./module-manager.md) {prereq} +- [Module Manager](./01-module-manager.md) {prereq} ## BeginBlocker and EndBlocker `BeginBlocker` and `EndBlocker` are a way for module developers to add automatic execution of logic to their module. This is a powerful tool that should be used carefully, as complex automatic functions can slow down or even halt the chain. -When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`AppModule` interface](./module-manager.md#appmodule). The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. +When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`AppModule` interface](./01-module-manager.md#appmodule). The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. -The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./msg-services.md): +The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./03-msg-services.md): -- They generally use the [`keeper`](./keeper.md) and [`ctx`](../core/context.md) to retrieve information about the latest state. +- They generally use the [`keeper`](./06-keeper.md) and [`ctx`](../01-tx-lifecycle.md02-context.md) to retrieve information about the latest state. - If needed, they use the `keeper` and `ctx` to trigger state-transitions. -- If needed, they can emit [`events`](../core/events.md) via the `ctx`'s `EventManager`. +- If needed, they can emit [`events`](../01-tx-lifecycle.md07-events.md) via the `ctx`'s `EventManager`. A specificity of the `EndBlocker` is that it can return validator updates to the underlying consensus engine in the form of an [`[]abci.ValidatorUpdates`](https://tendermint.com/docs/app-dev/abci-spec.html#validatorupdate). This is the preferred way to implement custom validator changes. -It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). +It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./01-module-manager.md#manager). See an example implementation of `BeginBlocker` from the `distr` module: @@ -36,4 +32,4 @@ and an example implementation of `EndBlocker` from the `staking` module: ## Next {hide} -Learn about [`keeper`s](./keeper.md) {hide} +Learn about [`keeper`s](./06-keeper.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/keeper.md b/versioned_docs/version-0.45/integrate/building-modules/06-keeper.md similarity index 70% rename from versioned_docs/version-0.45/integrate/building-modules/keeper.md rename to versioned_docs/version-0.45/integrate/building-modules/06-keeper.md index 0f82ccd2e..fb66377aa 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/keeper.md +++ b/versioned_docs/version-0.45/integrate/building-modules/06-keeper.md @@ -1,7 +1,3 @@ - - # Keepers `Keeper`s refer to a Cosmos SDK abstraction whose role is to manage access to the subset of the state defined by various modules. `Keeper`s are module-specific, i.e. the subset of state defined by a module can only be accessed by a `keeper` defined in said module. If a module needs to access the subset of state defined by another module, a reference to the second module's internal `keeper` needs to be passed to the first one. This is done in `app.go` during the instantiation of module keepers. {synopsis} @@ -14,9 +10,9 @@ order: 7 The Cosmos SDK is a framework that makes it easy for developers to build complex decentralised applications from scratch, mainly by composing modules together. As the ecosystem of open source modules for the Cosmos SDK expands, it will become increasingly likely that some of these modules contain vulnerabilities, as a result of the negligence or malice of their developer. -The Cosmos SDK adopts an [object-capabilities-based approach](../core/ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be thought of quite literally as the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../core/store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). +The Cosmos SDK adopts an [object-capabilities-based approach](../advanced-concepts/ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be thought of quite literally as the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../advanced-concepts/04-store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). -The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../basics/app-anatomy.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. +The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. ## Type Definition @@ -39,14 +35,14 @@ For example, here is the type definition of the `keeper` from the `staking` modu Let us go through the different parameters: - An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself. -- `storeKey`s grant access to the store(s) of the [multistore](../core/store.md) managed by the module. They should always remain unexposed to external modules. -- `cdc` is the [codec](../core/encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. +- `storeKey`s grant access to the store(s) of the [multistore](../advanced-concepts/04-store.md) managed by the module. They should always remain unexposed to external modules. +- `cdc` is the [codec](../advanced-concepts/05-encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. -Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../basics/app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. +Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../high-level-concepts/app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. ## Implementing Methods -`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed via the `ValidateBasic()` method of the [`message`](./messages-and-queries.md#messages) and the [`Msg` server](./msg-services.md) when `keeper`s' methods are called. +`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed via the `ValidateBasic()` method of the [`message`](./02-messages-and-queries.md#messages) and the [`Msg` server](./03-msg-services.md) when `keeper`s' methods are called. Typically, a *getter* method will have the following signature @@ -74,7 +70,7 @@ and the method will go through the following steps: For more, see an example of `keeper`'s [methods implementation from the `staking` module](https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/staking/keeper/keeper.go). -The [module `KVStore`](../core/store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. +The [module `KVStore`](../core/04-store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. This is an example from the `auth` module to iterate accounts: @@ -82,4 +78,4 @@ This is an example from the `auth` module to iterate accounts: ## Next {hide} -Learn about [invariants](./invariants.md) {hide} +Learn about [invariants](./07-invariants.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/invariants.md b/versioned_docs/version-0.45/integrate/building-modules/07-invariants.md similarity index 82% rename from versioned_docs/version-0.45/integrate/building-modules/invariants.md rename to versioned_docs/version-0.45/integrate/building-modules/07-invariants.md index 0adce4dc1..6525111f2 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/invariants.md +++ b/versioned_docs/version-0.45/integrate/building-modules/07-invariants.md @@ -1,14 +1,10 @@ - - # Invariants An invariant is a property of the application that should always be true. In the context of the Cosmos SDK, an `Invariant` is a function that checks for a particular invariant. These functions are useful to detect bugs early on and act upon them to limit their potential consequences (e.g. by halting the chain). They are also useful in the development process of the application to detect bugs via simulations. {synopsis} ## Pre-requisite Readings -- [Keepers](./keeper.md) {prereq} +- [Keepers](./06-keeper.md) {prereq} ## Implementing `Invariant`s @@ -49,7 +45,7 @@ func AllInvariants(k Keeper) sdk.Invariant { } ``` -Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](./module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): +Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](./01-module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): ```go // RegisterInvariants registers all staking invariants @@ -75,9 +71,9 @@ Typically, this interface is implemented in the `keeper` of a specific module. T +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/crisis/keeper/keeper.go#L50-L54 - The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../basics/app-anatomy.md#constructor-function). + The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function). -`Invariant`s can be checked manually via [`message`s](./messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: +`Invariant`s can be checked manually via [`message`s](./02-messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/crisis/abci.go#L7-L14 @@ -85,4 +81,4 @@ In both cases, if one of the `Invariant`s returns false, the `InvariantRegistry` ## Next {hide} -Learn about [genesis functionalities](./genesis.md) {hide} +Learn about [genesis functionalities](./08-genesis.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/genesis.md b/versioned_docs/version-0.45/integrate/building-modules/08-genesis.md similarity index 62% rename from versioned_docs/version-0.45/integrate/building-modules/genesis.md rename to versioned_docs/version-0.45/integrate/building-modules/08-genesis.md index 7ad32b4d4..33a2e10d7 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/genesis.md +++ b/versioned_docs/version-0.45/integrate/building-modules/08-genesis.md @@ -1,19 +1,15 @@ - - # Module Genesis Modules generally handle a subset of the state and, as such, they need to define the related subset of the genesis file as well as methods to initialize, verify and export it. {synopsis} ## Pre-requisite Readings -- [Module Manager](./module-manager.md) {prereq} -- [Keepers](./keeper.md) {prereq} +- [Module Manager](./01-module-manager.md) {prereq} +- [Keepers](./06-keeper.md) {prereq} ## Type Definition -The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../core/encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. +The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../advanced-concepts/05-encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. See an example of `GenesisState` protobuf message definition from the `auth` module: @@ -35,13 +31,13 @@ The `ValidateGenesis(genesisState GenesisState)` method is called to verify that ## Other Genesis Methods -Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](./module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). +Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](./01-module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). ### `InitGenesis` -The `InitGenesis` method is executed during [`InitChain`](../core/baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](./keeper.md) setter function on each parameter within the `GenesisState`. +The `InitGenesis` method is executed during [`InitChain`](../../develop/advanced-concepts/00-baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](./06-keeper.md) setter function on each parameter within the `GenesisState`. -The [module manager](./module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../basics/app-anatomy.md#constructor-function). +The [module manager](./01-module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function). See an example of `InitGenesis` from the `auth` module: diff --git a/versioned_docs/version-0.45/integrate/building-modules/module-interfaces.md b/versioned_docs/version-0.45/integrate/building-modules/09-module-interfaces.md similarity index 84% rename from versioned_docs/version-0.45/integrate/building-modules/module-interfaces.md rename to versioned_docs/version-0.45/integrate/building-modules/09-module-interfaces.md index 161d9f455..195db13de 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/module-interfaces.md +++ b/versioned_docs/version-0.45/integrate/building-modules/09-module-interfaces.md @@ -1,7 +1,3 @@ - - # Module Interfaces This document details how to build CLI and REST interfaces for a module. Examples from various SDK modules are included. {synopsis} @@ -12,11 +8,11 @@ This document details how to build CLI and REST interfaces for a module. Example ## CLI -One of the main interfaces for an application is the [command-line interface](../core/cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](./messages-and-queries.md#messages) wrapped in transactions and [**queries**](./messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. +One of the main interfaces for an application is the [command-line interface](../advanced-concepts/06-cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](./02-messages-and-queries.md#messages) wrapped in transactions and [**queries**](./02-messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. ### Transaction Commands - In order to create messages that trigger state changes, end-users must create [transactions](../core/transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. + In order to create messages that trigger state changes, end-users must create [transactions](../core/01-transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. Transaction commands typically have their own `tx.go` file that lives within the module's `./client/cli` folder. The commands are specified in getter functions and the name of the function should include the name of the command. @@ -35,7 +31,7 @@ In general, the getter function does the following: - **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new transaction. - The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientTxContext(cmd)`. The `clientCtx` contains information relevant to transaction handling, including information about the user. In this example, the `clientCtx` is used to retrieve the address of the sender by calling `clientCtx.GetFromAddress()`. - If applicable, the command's arguments are parsed. In this example, the arguments `[to_address]` and `[amount]` are both parsed. - - A [message](./messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call [`msg.ValidateBasic()`](../basics/tx-lifecycle.md#ValidateBasic) and other validation methods before broadcasting the message. + - A [message](./02-messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call [`msg.ValidateBasic()`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) and other validation methods before broadcasting the message. - Depending on what the user wants, the transaction is either generated offline or signed and broadcasted to the preconfigured node using `tx.GenerateOrBroadcastTxCLI(clientCtx, flags, msg)`. - **Adds transaction flags:** All transaction commands must add a set of transaction [flags](#flags). The transaction flags are used to collect additional information from the user (e.g. the amount of fees the user is willing to pay). The transaction flags are added to the constructed command using `AddTxFlagsToCmd(cmd)`. - **Returns the command:** Finally, the transaction command is returned. @@ -50,7 +46,7 @@ Each module must also implement the `GetTxCmd()` method for `AppModuleBasic` tha ### Query Commands -[Queries](./messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: +[Queries](./02-messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-beta1/x/auth/client/cli/query.go#L75-L105 @@ -65,7 +61,7 @@ In general, the getter function does the following: - **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new query. - The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientQueryContext(cmd)`. The `clientCtx` contains information relevant to query handling. - If applicable, the command's arguments are parsed. In this example, the argument `[address]` is parsed. - - A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./messages-and-queries.md#grpc-queries). + - A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./02-messages-and-queries.md#grpc-queries). - The `clientCtx.PrintProto` method is used to format the `proto.Message` object so that the results can be printed back to the user. - **Adds query flags:** All query commands must add a set of query [flags](#flags). The query flags are added to the constructed command using `AddQueryFlagsToCmd(cmd)`. - **Returns the command:** Finally, the query command is returned. @@ -80,7 +76,7 @@ Each module must also implement the `GetQueryCmd()` method for `AppModuleBasic` ### Flags -[Flags](../core/cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../basics/gas-fees.md) and gas prices for their transactions. +[Flags](../core/06-cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../high-level-concepts/gas-fees.md) and gas prices for their transactions. Flags that are specific to a module are typically created in a `flags.go` file in the module's `./client/cli` folder. When creating a flag, developers set the value type, the name of the flag, the default value, and a description about the flag. Developers also have the option to mark flags as _required_ so that an error is thrown if the user does not include a value for the flag. @@ -136,4 +132,4 @@ The SDK provides a command for generating [Swagger](https://swagger.io/) documen ## Next {hide} -Read about the recommended [module structure](./structure.md) {hide} +Read about the recommended [module structure](./11-structure.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/structure.md b/versioned_docs/version-0.45/integrate/building-modules/10-structure.md similarity index 98% rename from versioned_docs/version-0.45/integrate/building-modules/structure.md rename to versioned_docs/version-0.45/integrate/building-modules/10-structure.md index 549cd634f..a43b946c2 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/structure.md +++ b/versioned_docs/version-0.45/integrate/building-modules/10-structure.md @@ -1,7 +1,3 @@ - - # Recommended Folder Structure This document outlines the recommended structure of Cosmos SDK modules. These ideas are meant to be applied as suggestions. Application developers are encouraged to improve upon and contribute to module structure and development design. {synopsis} @@ -96,4 +92,4 @@ x/{module_name} ## Next {hide} -Learn about [Errors](./errors.md) {hide} +Learn about [Errors](./12-errors.md) {hide} diff --git a/versioned_docs/version-0.45/integrate/building-modules/errors.md b/versioned_docs/version-0.45/integrate/building-modules/11-errors.md similarity index 99% rename from versioned_docs/version-0.45/integrate/building-modules/errors.md rename to versioned_docs/version-0.45/integrate/building-modules/11-errors.md index d1bc36824..85ca95368 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/errors.md +++ b/versioned_docs/version-0.45/integrate/building-modules/11-errors.md @@ -1,7 +1,3 @@ - - # Errors This document outlines the recommended usage and APIs for error handling in Cosmos SDK modules. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/building-modules/upgrade.md b/versioned_docs/version-0.45/integrate/building-modules/12-upgrade.md similarity index 97% rename from versioned_docs/version-0.45/integrate/building-modules/upgrade.md rename to versioned_docs/version-0.45/integrate/building-modules/12-upgrade.md index f1c37930c..a98eda6c9 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/upgrade.md +++ b/versioned_docs/version-0.45/integrate/building-modules/12-upgrade.md @@ -1,14 +1,10 @@ - - # Upgrading Modules [In-Place Store Migrations](../core/upgrade.html) allow your modules to upgrade to new versions that include breaking changes. This document outlines how to build modules to take advantage of this functionality. {synopsis} ## Prerequisite Readings -- [In-Place Store Migration](../core/upgrade.md) {prereq} +- [In-Place Store Migration](../core/13-upgrade.md) {prereq} ## Consensus Version diff --git a/versioned_docs/version-0.45/integrate/building-modules/simulator.md b/versioned_docs/version-0.45/integrate/building-modules/13-simulator.md similarity index 99% rename from versioned_docs/version-0.45/integrate/building-modules/simulator.md rename to versioned_docs/version-0.45/integrate/building-modules/13-simulator.md index e6f07fbb6..1ef579ab6 100644 --- a/versioned_docs/version-0.45/integrate/building-modules/simulator.md +++ b/versioned_docs/version-0.45/integrate/building-modules/13-simulator.md @@ -58,7 +58,7 @@ Operations are one of the crucial parts of the SDK simulation. They are the tran (`Msg`) that are simulated with random field values. The sender of the operation is also assigned randomly. -Operations on the simulation are simulated using the full [transaction cycle](../core/transactions.md) of a +Operations on the simulation are simulated using the full [transaction cycle](../core/01-transactions.md) of a `ABCI` application that exposes the `BaseApp`. Shown below is how weights are set: diff --git a/versioned_docs/version-0.45/integrate/building-modules/README.md b/versioned_docs/version-0.45/integrate/building-modules/README.md deleted file mode 100644 index 411c3e8d3..000000000 --- a/versioned_docs/version-0.45/integrate/building-modules/README.md +++ /dev/null @@ -1,23 +0,0 @@ - - -# Building Modules - -This repository contains documentation on concepts developers need to know in order to build modules for Cosmos SDK applications. - -1. [Introduction to Cosmos SDK Modules](./intro.md) -2. [`AppModule` Interface and Module Manager](./module-manager.md) -3. [Messages and Queries](./messages-and-queries.md) -4. [`Msg` services - Processing Messages](./msg-services.md) -5. [Query Services - Processing Queries](./query-services.md) -6. [BeginBlocker and EndBlocker](./beginblock-endblock.md) -7. [`Keeper`s](./keeper.md) -8. [Invariants](./invariants.md) -9. [Genesis](./genesis.md) -10. [Module Interfaces](./module-interfaces.md) -11. [Standard Module Structure](./structure.md) -12. [Errors](./errors.md) -13. [In-Place Store Migrations](./upgrade.md) diff --git a/versioned_docs/version-0.45/integrate/building-modules/_category_.json b/versioned_docs/version-0.45/integrate/building-modules/_category_.json new file mode 100644 index 000000000..2d50f8b3e --- /dev/null +++ b/versioned_docs/version-0.45/integrate/building-modules/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Building Modules", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/integrate/ibc/README.md b/versioned_docs/version-0.45/integrate/ibc/README.md deleted file mode 100644 index 8be696391..000000000 --- a/versioned_docs/version-0.45/integrate/ibc/README.md +++ /dev/null @@ -1,20 +0,0 @@ - - -# IBC - -This repository contains reference documentation for the IBC protocol integration and concepts: - -1. [Overview](./overview.md) -2. [Integration](./integration.md) -3. [Customization](./custom.md) -4. [Relayer](./relayer.md) -5. [Governance Proposals](./proposals.md) - -**NOTE**: The IBC module has been moved to its [own repository](https://github.com/cosmos/ibc-go). - -After reading about IBC, head on to the [Building Modules -documentation](../building-modules/README.md) to learn more about the process of building modules. diff --git a/versioned_docs/version-0.45/integrate/ibc/_category_.json b/versioned_docs/version-0.45/integrate/ibc/_category_.json new file mode 100644 index 000000000..c56117213 --- /dev/null +++ b/versioned_docs/version-0.45/integrate/ibc/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IBC", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/integrate/ibc/custom.md b/versioned_docs/version-0.45/integrate/ibc/custom.md index 36de3085c..0bef693f1 100644 --- a/versioned_docs/version-0.45/integrate/ibc/custom.md +++ b/versioned_docs/version-0.45/integrate/ibc/custom.md @@ -1,7 +1,3 @@ - - # Customization Learn how to configure your application to use IBC and send data packets to other chains. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/ibc/integration.md b/versioned_docs/version-0.45/integrate/ibc/integration.md index ec48126fd..e8506ca6c 100644 --- a/versioned_docs/version-0.45/integrate/ibc/integration.md +++ b/versioned_docs/version-0.45/integrate/ibc/integration.md @@ -1,7 +1,3 @@ - - # Integration Learn how to integrate IBC to your application and send data packets to other chains. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/ibc/overview.md b/versioned_docs/version-0.45/integrate/ibc/overview.md index 6aca66899..6b739d93d 100644 --- a/versioned_docs/version-0.45/integrate/ibc/overview.md +++ b/versioned_docs/version-0.45/integrate/ibc/overview.md @@ -1,5 +1,3 @@ - - # IBC Overview Learn what IBC is, its components, and use cases. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/ibc/proposals.md b/versioned_docs/version-0.45/integrate/ibc/proposals.md index d82609262..064858311 100644 --- a/versioned_docs/version-0.45/integrate/ibc/proposals.md +++ b/versioned_docs/version-0.45/integrate/ibc/proposals.md @@ -1,7 +1,3 @@ - - # Governance Proposals In uncommon situations, a highly valued client may become frozen due to uncontrollable diff --git a/versioned_docs/version-0.45/integrate/ibc/relayer.md b/versioned_docs/version-0.45/integrate/ibc/relayer.md index 0e59885c8..74e57e65f 100644 --- a/versioned_docs/version-0.45/integrate/ibc/relayer.md +++ b/versioned_docs/version-0.45/integrate/ibc/relayer.md @@ -1,13 +1,9 @@ - - # Relayer ## Prerequisites Readings - [IBC Overview](./overview.md) {prereq} -- [Events](https://github.com/cosmos/cosmos-sdk/blob/master/docs/core/events.md) {prereq} +- [Events](https://github.com/cosmos/cosmos-sdk/blob/master/docs/core/07-events.md) {prereq} ## Events diff --git a/versioned_docs/version-0.45/integrate/ibc/upgrades/_category_.json b/versioned_docs/version-0.45/integrate/ibc/upgrades/_category_.json new file mode 100644 index 000000000..4305ecc6a --- /dev/null +++ b/versioned_docs/version-0.45/integrate/ibc/upgrades/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Upgrades", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/integrate/ibc/upgrades/developer-guide.md b/versioned_docs/version-0.45/integrate/ibc/upgrades/developer-guide.md index d41b3346d..41990abfe 100644 --- a/versioned_docs/version-0.45/integrate/ibc/upgrades/developer-guide.md +++ b/versioned_docs/version-0.45/integrate/ibc/upgrades/developer-guide.md @@ -1,7 +1,3 @@ - - # IBC Client Developer Guide to Upgrades Learn how to implement upgrade functionality for your custom IBC client. {synopsis} diff --git a/versioned_docs/version-0.45/integrate/ibc/upgrades/quick-guide.md b/versioned_docs/version-0.45/integrate/ibc/upgrades/quick-guide.md index d277de14f..22ff139b5 100644 --- a/versioned_docs/version-0.45/integrate/ibc/upgrades/quick-guide.md +++ b/versioned_docs/version-0.45/integrate/ibc/upgrades/quick-guide.md @@ -1,7 +1,3 @@ - - # How to Upgrade IBC Chains and their Clients Learn how to upgrade your chain and counterparty clients. {synopsis} diff --git a/versioned_docs/version-0.45/user/_category_.json b/versioned_docs/version-0.45/user/_category_.json new file mode 100644 index 000000000..ac5540cce --- /dev/null +++ b/versioned_docs/version-0.45/user/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "`User`", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.45/user/run-node/keyring.md b/versioned_docs/version-0.45/user/run-node/00-keyring.md similarity index 96% rename from versioned_docs/version-0.45/user/run-node/keyring.md rename to versioned_docs/version-0.45/user/run-node/00-keyring.md index 711dccbd0..81488c81d 100644 --- a/versioned_docs/version-0.45/user/run-node/keyring.md +++ b/versioned_docs/version-0.45/user/run-node/00-keyring.md @@ -1,6 +1,6 @@ # Setting up the keyring -This document describes how to configure and use the keyring and its various backends for an [**application**](../basics/app-anatomy.md). {synopsis} +This document describes how to configure and use the keyring and its various backends for an [**application**](../high-level-concepts/app-anatomy.md). {synopsis} The keyring holds the private/public keypairs used to interact with a node. For instance, a validator key needs to be set up before running the blockchain node, so that blocks can be correctly signed. The private key can be stored in different locations, called "backends", such as a file or the operating system's own key storage. @@ -125,7 +125,7 @@ MY_VALIDATOR_ADDRESS=$(simd keys show my_validator -a --keyring-backend test) This command generates a new 24-word mnemonic phrase, persists it to the relevant backend, and outputs information about the keypair. If this keypair will be used to hold value-bearing tokens, be sure to write down the mnemonic phrase somewhere safe! -By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [AnteHandlers](../core/baseapp.md#antehandler)) supports natively these two public key algorithms. +By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [AnteHandlers](../../develop/advanced-concepts/00-baseapp.md#antehandler)) supports natively these two public key algorithms. ## Next {hide} diff --git a/versioned_docs/version-0.45/user/run-node/run-node.md b/versioned_docs/version-0.45/user/run-node/01-run-node.md similarity index 98% rename from versioned_docs/version-0.45/user/run-node/run-node.md rename to versioned_docs/version-0.45/user/run-node/01-run-node.md index d044ce763..69fe24f29 100644 --- a/versioned_docs/version-0.45/user/run-node/run-node.md +++ b/versioned_docs/version-0.45/user/run-node/01-run-node.md @@ -4,7 +4,7 @@ Now that the application is ready and the keyring populated, it's time to see ho ## Pre-requisite Readings -- [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq} +- [Anatomy of an SDK Application](../high-level-concepts/app-anatomy.md) {prereq} - [Setting up the keyring](./keyring.md) {prereq} ## Initialize the Chain diff --git a/versioned_docs/version-0.45/user/run-node/interact-node.md b/versioned_docs/version-0.45/user/run-node/02-interact-node.md similarity index 93% rename from versioned_docs/version-0.45/user/run-node/interact-node.md rename to versioned_docs/version-0.45/user/run-node/02-interact-node.md index b1e375e6c..16dac21d6 100644 --- a/versioned_docs/version-0.45/user/run-node/interact-node.md +++ b/versioned_docs/version-0.45/user/run-node/02-interact-node.md @@ -4,7 +4,7 @@ There are multiple ways to interact with a node: using the CLI, using gRPC or us ## Pre-requisite Readings -- [gRPC, REST and Tendermint Endpoints](../core/grpc_rest.md) {prereq} +- [gRPC, REST and Tendermint Endpoints](../core/08-grpc_rest.md) {prereq} - [Running a Node](./run-node.md) {prereq} ## Using the CLI @@ -46,7 +46,7 @@ You should see two delegations, the first one made from the `gentx`, and the sec ## Using gRPC -The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/grpc_rest.md). +The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/08-grpc_rest.md). Since the code generation library largely depends on your own tech stack, we will only present three alternatives: @@ -189,7 +189,7 @@ CosmJS documentation can be found at [https://cosmos.github.io/cosmjs](https://c ## Using the REST Endpoints -As described in the [gRPC guide](../core/grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. +As described in the [gRPC guide](../core/08-grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. As a concrete example, the `curl` command to make balances request is: diff --git a/versioned_docs/version-0.45/user/run-node/txs.md b/versioned_docs/version-0.45/user/run-node/03-txs.md similarity index 99% rename from versioned_docs/version-0.45/user/run-node/txs.md rename to versioned_docs/version-0.45/user/run-node/03-txs.md index 248f1b222..e54314630 100644 --- a/versioned_docs/version-0.45/user/run-node/txs.md +++ b/versioned_docs/version-0.45/user/run-node/03-txs.md @@ -237,7 +237,7 @@ func sendTx() error { ### Broadcasting a Transaction -The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the Tendermint RPC is also posible. An overview of the differences between these methods is exposed [here](../core/grpc_rest.md). For this tutorial, we will only describe the gRPC method. +The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the Tendermint RPC is also posible. An overview of the differences between these methods is exposed [here](../core/08-grpc_rest.md). For this tutorial, we will only describe the gRPC method. ```go import ( diff --git a/versioned_docs/version-0.45/user/run-node/rosetta.md b/versioned_docs/version-0.45/user/run-node/04-rosetta.md similarity index 100% rename from versioned_docs/version-0.45/user/run-node/rosetta.md rename to versioned_docs/version-0.45/user/run-node/04-rosetta.md diff --git a/versioned_docs/version-0.45/user/run-node/run-testnet.md b/versioned_docs/version-0.45/user/run-node/05-run-testnet.md similarity index 100% rename from versioned_docs/version-0.45/user/run-node/run-testnet.md rename to versioned_docs/version-0.45/user/run-node/05-run-testnet.md diff --git a/versioned_docs/version-0.45/user/run-node/_category_.json b/versioned_docs/version-0.45/user/run-node/_category_.json new file mode 100644 index 000000000..2658bb66c --- /dev/null +++ b/versioned_docs/version-0.45/user/run-node/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Run Node", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/develop/_category_.json b/versioned_docs/version-0.46/develop/_category_.json new file mode 100644 index 000000000..f40637f4d --- /dev/null +++ b/versioned_docs/version-0.46/develop/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Develop", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/00-baseapp.md b/versioned_docs/version-0.46/develop/advanced-concepts/00-baseapp.md index 7aee39deb..cce8b5b99 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/00-baseapp.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/00-baseapp.md @@ -4,8 +4,8 @@ This document describes `BaseApp`, the abstraction that implements the core func ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {prereq} -* [Lifecycle of a Cosmos SDK transaction](../basics/tx-lifecycle.md) {prereq} +* [Anatomy of a Cosmos SDK application](../high-level-concepts/00-overview-app.md) {prereq} +* [Lifecycle of a Cosmos SDK transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Introduction @@ -69,8 +69,8 @@ First, the important parameters that are initialized during the bootstrapping of * [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment, and other pre-message execution checks when a transaction is received. It's executed during [`CheckTx/RecheckTx`](#checktx) and [`DeliverTx`](#delivertx). -* [`InitChainer`](../basics/app-anatomy.md#initchainer), - [`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): These are +* [`InitChainer`](../high-level-concepts/00-overview-app.md#initchainer), + [`BeginBlocker` and `EndBlocker`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblocker): These are the functions executed when the application receives the `InitChain`, `BeginBlock` and `EndBlock` ABCI messages from the underlying Tendermint engine. @@ -94,7 +94,7 @@ Finally, a few more important parameters: `minGasPrices` (e.g. if `minGasPrices == 1uatom,1photon`, the `gas-price` of the transaction must be greater than `1uatom` OR `1photon`). * `appVersion`: Version of the application. It is set in the - [application's constructor function](../basics/app-anatomy.md#constructor-function). + [application's constructor function](../high-level-concepts/00-overview-app.md#constructor-function). ## Constructor @@ -187,17 +187,17 @@ When messages and queries are received by the application, they must be routed t ### `Msg` Service Router -[`sdk.Msg`s](#../building-modules/messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. +[`sdk.Msg`s](#../building-modules/02-messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. The [default `msgServiceRouter` included in `BaseApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/baseapp/msg_service_router.go) is stateless. However, some applications may want to make use of more stateful routing mechanisms such as allowing governance to disable certain routes or point them to new modules for upgrade purposes. For this reason, the `sdk.Context` is also passed into each [route handler inside `msgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/baseapp/msg_service_router.go#L31-L32). For a stateless router that doesn't want to make use of this, you can just ignore the `ctx`. -The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#constructor-function). +The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/01-module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#constructor-function). ### gRPC Query Router -Similar to `sdk.Msg`s, [`queries`](../building-modules/messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint. +Similar to `sdk.Msg`s, [`queries`](../building-modules/02-messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/04-query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint. -Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor). +Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/01-module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#app-constructor). ## Main ABCI Messages @@ -229,16 +229,16 @@ to do the following checks: 2. Perform _stateless_ checks by calling `ValidateBasic()` on each of the `sdk.Msg`s. This is done first, as _stateless_ checks are less computationally expensive than _stateful_ checks. If `ValidateBasic()` fail, `CheckTx` returns before running _stateful_ checks, which saves resources. -3. Perform non-module related _stateful_ checks on the [account](../basics/accounts.md). This step is mainly about checking +3. Perform non-module related _stateful_ checks on the [account](../high-level-concepts/03-accounts.md). This step is mainly about checking that the `sdk.Msg` signatures are valid, that enough fees are provided and that the sending account - has enough funds to pay for said fees. Note that no precise [`gas`](../basics/gas-fees.md) counting occurs here, - as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../basics/gas-fees.md#antehandler) will check that the `gas` provided + has enough funds to pay for said fees. Note that no precise [`gas`](../high-level-concepts/gas-fees.md) counting occurs here, + as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) will check that the `gas` provided with the transaction is superior to a minimum reference gas amount based on the raw transaction size, in order to avoid spam with transactions that provide 0 gas. `CheckTx` does **not** process `sdk.Msg`s - they only need to be processed when the canonical state need to be updated, which happens during `DeliverTx`. -Steps 2. and 3. are performed by the [`AnteHandler`](../basics/gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs) +Steps 2. and 3. are performed by the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs) function, which `CheckTx()` calls with the `runTxModeCheck` mode. During each step of `CheckTx()`, a special [volatile state](#state-updates) called `checkState` is updated. This state is used to keep track of the temporary changes triggered by the `CheckTx()` calls of each transaction without modifying @@ -281,7 +281,7 @@ Before the first transaction of a given block is processed, a [volatile state](# `DeliverTx` performs the **exact same steps as `CheckTx`**, with a little caveat at step 3 and the addition of a fifth step: 1. The `AnteHandler` does **not** check that the transaction's `gas-prices` is sufficient. That is because the `min-gas-prices` value `gas-prices` is checked against is local to the node, and therefore what is enough for one full-node might not be for another. This means that the proposer can potentially include transactions for free, although they are not incentivised to do so, as they earn a bonus on the total fee of the block they propose. -2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. +2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: @@ -306,7 +306,7 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0 `RunTx` is called from `CheckTx`/`DeliverTx` to handle the transaction, with `runTxModeCheck` or `runTxModeDeliver` as parameter to differentiate between the two modes of execution. Note that when `RunTx` receives a transaction, it has already been decoded. -The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../basics/gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. +The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../high-level-concepts/gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. After that, `RunTx()` calls `ValidateBasic()` on each `sdk.Msg`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `sdk.Msg` fails to pass `ValidateBasic()`, `RunTx()` returns with an error. @@ -330,15 +330,15 @@ The `AnteHandler` is theoretically optional, but still a very important componen * Perform preliminary _stateful_ validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees. * Play a role in the incentivisation of stakeholders via the collection of transaction fees. -`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/auth/ante/ante.go). +`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../high-level-concepts/00-overview-app.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/auth/ante/ante.go). -Click [here](../basics/gas-fees.md#antehandler) for more on the `anteHandler`. +Click [here](../high-level-concepts/gas-fees.md#antehandler) for more on the `anteHandler`. ### RunMsgs `RunMsgs` is called from `RunTx` with `runTxModeCheck` as parameter to check the existence of a route for each message the transaction, and with `runTxModeDeliver` to actually process the `sdk.Msg`s. -First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/msg-services.md) RPC is executed, before `RunMsgs` returns. +First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/03-msg-services.md) RPC is executed, before `RunMsgs` returns. ### PostHandler @@ -359,9 +359,9 @@ The [`InitChain` ABCI message](https://docs.tendermint.com/master/spec/abci/abci * [Consensus Parameters](https://docs.tendermint.com/master/spec/abci/apps.html#consensus-parameters) via `setConsensusParams`. * [`checkState` and `deliverState`](#state-updates) via `setCheckState` and `setDeliverState`. -* The [block gas meter](../basics/gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. +* The [block gas meter](../high-level-concepts/gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. -Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../basics/app-anatomy.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules. +Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../high-level-concepts/00-overview-app.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/08-genesis.md#initgenesis) function of each of the application's modules. ### BeginBlock @@ -369,14 +369,14 @@ The [`BeginBlock` ABCI message](https://docs.tendermint.com/master/spec/abci/abc * Initialize [`deliverState`](#state-updates) with the latest header using the `req abci.RequestBeginBlock` passed as parameter via the `setDeliverState` function. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/baseapp/baseapp.go#L386-L396 - This function also resets the [main gas meter](../basics/gas-fees.md#main-gas-meter). -* Initialize the [block gas meter](../basics/gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. -* Run the application's [`beginBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. + This function also resets the [main gas meter](../high-level-concepts/04-gas-fees.md#main-gas-meter). +* Initialize the [block gas meter](../high-level-concepts/04-gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. +* Run the application's [`beginBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. * Set the [`VoteInfos`](https://docs.tendermint.com/master/spec/abci/abci.html#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./03-context.md) so that it can be used during `DeliverTx` and `EndBlock`. ### EndBlock -The [`EndBlock` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. +The [`EndBlock` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules. ### Commit @@ -392,14 +392,14 @@ The [`Info` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.html ### Query -The [`Query` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.html#query-2) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../building-modules/query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://docs.tendermint.com/master/spec/abci/apps.html#query). +The [`Query` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.html#query-2) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../building-modules/04-query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://docs.tendermint.com/master/spec/abci/apps.html#query). Each Tendermint `query` comes with a `path`, which is a `string` which denotes what to query. If the `path` matches a gRPC fully-qualified service method, then `BaseApp` will defer the query to the `grpcQueryRouter` and let it handle it like explained [above](#grpc-query-router). Otherwise, the `path` represents a query that is not (yet) handled by the gRPC router. `BaseApp` splits the `path` string with the `/` delimiter. By convention, the first element of the split string (`split[0]`) contains the category of `query` (`app`, `p2p`, `store` or `custom` ). The `BaseApp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving these 4 main categories of queries: * Application-related queries like querying the application's version, which are served via the `handleQueryApp` method. * Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queries are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers. * P2P queries, which are served via the `handleQueryP2P` method. These queries return either `app.addrPeerFilter` or `app.ipPeerFilter` that contain the list of peers filtered by address or IP respectively. These lists are first initialized via `options` in `BaseApp`'s [constructor](#constructor). -* Custom queries, which encompass legacy queries (before the introduction of gRPC queries), are served via the `handleQueryCustom` method. The `handleQueryCustom` branches the multistore before using the `queryRoute` obtained from `app.queryRouter` to map the query to the appropriate module's [legacy `querier`](../building-modules/query-services.md#legacy-queriers). +* Custom queries, which encompass legacy queries (before the introduction of gRPC queries), are served via the `handleQueryCustom` method. The `handleQueryCustom` branches the multistore before using the `queryRoute` obtained from `app.queryRouter` to map the query to the appropriate module's [legacy `querier`](../building-modules/04-query-services.md#legacy-queriers). ## Next {hide} diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/01-transactions.md b/versioned_docs/version-0.46/develop/advanced-concepts/01-transactions.md index aba1e01ca..51628fef3 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/01-transactions.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/01-transactions.md @@ -1,20 +1,16 @@ - - # Transactions `Transactions` are objects created by end-users to trigger state changes in the application. {synopsis} ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](../basics/app-anatomy.md) {prereq} +* [Anatomy of a Cosmos SDK Application](../high-level-concepts/app-anatomy.md) {prereq} ## Transactions -Transactions are comprised of metadata held in [contexts](./03-context.md) and [`sdk.Msg`s](../building-modules/messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../building-modules/msg-services.md). +Transactions are comprised of metadata held in [contexts](./03-context.md) and [`sdk.Msg`s](../building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). -When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../basics/tx-lifecycle.md). +When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../high-level-concepts/01-tx-lifecycle.md). ## Type Definition @@ -25,7 +21,7 @@ Transaction objects are Cosmos SDK types that implement the `Tx` interface It contains the following methods: * **GetMsgs:** unwraps the transaction and returns a list of contained `sdk.Msg`s - one transaction may have one or multiple messages, which are defined by module developers. -* **ValidateBasic:** lightweight, [_stateless_](../basics/tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./00-baseapp.md#checktx) and [`DeliverTx`](./00-baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth) module's `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from `sdk.Msg` [`ValidateBasic`](../basics/tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./00-baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. +* **ValidateBasic:** lightweight, [_stateless_](../high-level-concepts/01-tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./00-baseapp.md#checktx) and [`DeliverTx`](./00-baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth) module's `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from `sdk.Msg` [`ValidateBasic`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./00-baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. As a developer, you should rarely manipulate `Tx` directly, as `Tx` is really an intermediate type used for transaction generation. Instead, developers should prefer the `TxBuilder` interface, which you can learn more about [below](#transaction-generation). @@ -93,12 +89,12 @@ The next paragraphs will describe each of these components, in this order. Module `sdk.Msg`s are not to be confused with [ABCI Messages](https://docs.tendermint.com/master/spec/abci/abci.html#messages) which define interactions between the Tendermint and application layers. ::: -**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../building-modules/msg-services.md), and also implement the corresponding `MsgServer`. +**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../building-modules/03-msg-services.md), and also implement the corresponding `MsgServer`. -Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../building-modules/msg-services.md) RPC, defined inside each module's `tx.proto` file. A SDK app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. +Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../building-modules/03-msg-services.md) RPC, defined inside each module's `tx.proto` file. A SDK app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. This design puts more responsibility on module developers, allowing application developers to reuse common functionalities without having to implement state transition logic repetitively. -To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../building-modules/msg-services.md). +To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../building-modules/03-msg-services.md). While messages contain the information for state transition logic, a transaction's other metadata and relevant information are stored in the `TxBuilder` and `Context`. @@ -142,9 +138,9 @@ Once the transaction bytes are generated, there are currently three ways of broa #### CLI -Application developers create entry points to the application by creating a [command-line interface](../core/cli.md), [gRPC and/or REST interface](../core/grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. +Application developers create entry points to the application by creating a [command-line interface](../advanced-concepts/06-cli.md), [gRPC and/or REST interface](../advanced-concepts/08-grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. -For the [command-line interface](../building-modules/module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../run-node/interact-node.md) section. An example transaction made using CLI looks like: +For the [command-line interface](../building-modules/09-module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../run-node/interact-node.md) section. An example transaction made using CLI looks like: ```bash simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/03-context.md b/versioned_docs/version-0.46/develop/advanced-concepts/03-context.md index 75e374e0d..4f7dff139 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/03-context.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/03-context.md @@ -1,15 +1,11 @@ - - # Context The `context` is a data structure intended to be passed from function to function that carries information about the current state of the application. It provides access to a branched storage (a safe branch of the entire state) as well as useful objects and information like `gasMeter`, `block height`, `consensus parameters` and more. {synopsis} ## Pre-requisites Readings -* [Anatomy of a Cosmos SDK Application](../basics/app-anatomy.md) {prereq} -* [Lifecycle of a Transaction](../basics/tx-lifecycle.md) {prereq} +* [Anatomy of a Cosmos SDK Application](../high-level-concepts/app-anatomy.md) {prereq} +* [Lifecycle of a Transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Context Definition @@ -19,15 +15,15 @@ The Cosmos SDK `Context` is a custom data structure that contains Go's stdlib [` * **Base Context:** The base type is a Go [Context](https://pkg.go.dev/context), which is explained further in the [Go Context Package](#go-context-package) section below. * **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](./05-store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](./05-store.md#base-layer-kvstores) using their unique `StoreKey`. -* **Header:** The [header](https://docs.tendermint.com/master/spec/core/data_structures.html#header) is a Blockchain type. It carries important information about the state of the blockchain, such as block height and proposer of the current block. +* **Header:** The [header](https://docs.tendermint.com/master/spec/advanced-concepts/data_structures.html#header) is a Blockchain type. It carries important information about the state of the blockchain, such as block height and proposer of the current block. * **Header Hash:** The current block header hash, obtained during `abci.RequestBeginBlock`. * **Chain ID:** The unique identification number of the blockchain a block pertains to. -* **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the Cosmos SDK and consensus engine (e.g. Tendermint) throughout its [lifecycle](../basics/tx-lifecycle.md), some of which do not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./07-encoding.md) such as [Amino](./07-encoding.md). +* **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the Cosmos SDK and consensus engine (e.g. Tendermint) throughout its [lifecycle](../high-level-concepts/01-tx-lifecycle.md), some of which do not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./07-encoding.md) such as [Amino](./07-encoding.md). * **Logger:** A `logger` from the Tendermint libraries. Learn more about logs [here](https://docs.tendermint.com/master/nodes/logging.html). Modules call this method to create their own unique module-specific logger. * **VoteInfo:** A list of the ABCI type [`VoteInfo`](https://docs.tendermint.com/master/spec/abci/abci.html#voteinfo), which includes the name of a validator and a boolean indicating whether they have signed the block. -* **Gas Meters:** Specifically, a [`gasMeter`](../basics/gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../basics/gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../basics/gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. +* **Gas Meters:** Specifically, a [`gasMeter`](../high-level-concepts/gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../high-level-concepts/gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../high-level-concepts/gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. * **CheckTx Mode:** A boolean value indicating whether a transaction should be processed in `CheckTx` or `DeliverTx` mode. -* **Min Gas Price:** The minimum [gas](../basics/gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. +* **Min Gas Price:** The minimum [gas](../high-level-concepts/gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. * **Consensus Params:** The ABCI type [Consensus Parameters](https://docs.tendermint.com/master/spec/abci/apps.html#consensus-parameters), which specify certain limits for the blockchain, such as maximum gas for a block. * **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](./10-events.md). Modules may define module specific `Events` by defining various `Types` and `Attributes` or use the common definitions found in `types/`. Clients can subscribe or query for these `Events`. These `Events` are collected throughout `DeliverTx`, `BeginBlock`, and `EndBlock` and are returned to Tendermint for indexing. For example: diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/04-node.md b/versioned_docs/version-0.46/develop/advanced-concepts/04-node.md index 94b6e9a1a..185f767b7 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/04-node.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/04-node.md @@ -1,14 +1,10 @@ - - # Node Client (Daemon) The main endpoint of a Cosmos SDK application is the daemon client, otherwise known as the full-node client. The full-node runs the state-machine, starting from a genesis file. It connects to peers running the same client in order to receive and relay transactions, block proposals and signatures. The full-node is constituted of the application, defined with the Cosmos SDK, and of a consensus engine connected to the application via the ABCI. {synopsis} ## Pre-requisite Readings -* [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +* [Anatomy of an SDK application](../high-level-concepts/app-anatomy.md) {prereq} ## `main` function @@ -17,7 +13,7 @@ The full-node client of any Cosmos SDK application is built by running a `main` In general, developers will implement the `main.go` function with the following structure: * First, an [`encodingCodec`](./07-encoding.md) is instantiated for the application. -* Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../basics/accounts.md#addresses). +* Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../high-level-concepts/03-accounts.md#addresses). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/types/config.go#L14-L29 * Using [cobra](https://github.com/spf13/cobra), the root command of the full-node client is created. After that, all the custom commands of the application are added using the `AddCommand()` method of `rootCmd`. * Add default server commands to `rootCmd` using the `server.AddCommands()` method. These commands are separated from the ones added above since they are standard and defined at Cosmos SDK level. They should be shared by all Cosmos SDK-based applications. They include the most important command: the [`start` command](#start-command). @@ -52,7 +48,7 @@ Note that an `appCreator` is a function that fulfills the `AppCreator` signature +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/server/types/app.go#L57-L59 -In practice, the [constructor of the application](../basics/app-anatomy.md#constructor-function) is passed as the `appCreator`. +In practice, the [constructor of the application](../high-level-concepts/app-anatomy.md#constructor-function) is passed as the `appCreator`. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/simapp/simd/cmd/root.go#L246-L295 diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/05-store.md b/versioned_docs/version-0.46/develop/advanced-concepts/05-store.md index f6fe3fa96..e33046f8a 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/05-store.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/05-store.md @@ -1,18 +1,14 @@ - - # Store A store is a data structure that holds the state of the application. {synopsis} ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {prereq} +* [Anatomy of a Cosmos SDK application](../high-level-concepts/app-anatomy.md) {prereq} ## Introduction to Cosmos SDK Stores -The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of Cosmos SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store. +The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of Cosmos SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/06-keeper.md) of the module that declared the store. ```text +-----------------------------------------------------+ @@ -116,9 +112,9 @@ Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](http A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer. -Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store. +Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/06-keeper.md) of the module that defines the store. -`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. +`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../high-level-concepts/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/store/types/store.go#L192-L226 @@ -188,7 +184,7 @@ This is the type used whenever an IAVL Store needs to be branched to create an i ### `GasKv` Store -Cosmos SDK applications use [`gas`](../basics/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications. +Cosmos SDK applications use [`gas`](../high-level-concepts/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/store/gaskv/store.go#L11-L17 diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/07-encoding.md b/versioned_docs/version-0.46/develop/advanced-concepts/07-encoding.md index 47a2e34ff..5d531287b 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/07-encoding.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/07-encoding.md @@ -1,14 +1,10 @@ - - # Encoding While encoding in the Cosmos SDK used to be mainly handled by `go-amino` codec, the Cosmos SDK is moving towards using `gogoprotobuf` for both state and client-side encoding. {synopsis} ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {prereq} +* [Anatomy of a Cosmos SDK application](../high-level-concepts/app-anatomy.md) {prereq} ## Encoding @@ -121,7 +117,7 @@ See [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) for deta ### Interface Encoding and Usage of `Any` -The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../basics/accounts.md): +The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../high-level-concepts/03-accounts.md): ```proto message Profile { @@ -231,9 +227,9 @@ A real-life example of encoding the pubkey as `Any` inside the Validator struct Protobuf types can be defined to encode: * state -* [`Msg`s](../building-modules/messages-and-queries.md#messages) -* [Query services](../building-modules/query-services.md) -* [genesis](../building-modules/genesis.md) +* [`Msg`s](../building-modules/02-messages-and-queries.md#messages) +* [Query services](../building-modules/04-query-services.md) +* [genesis](../building-modules/08-genesis.md) #### Naming and conventions diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/08-grpc_rest.md b/versioned_docs/version-0.46/develop/advanced-concepts/08-grpc_rest.md index 3071a0a95..1adff19e0 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/08-grpc_rest.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/08-grpc_rest.md @@ -1,7 +1,3 @@ - - # gRPC, REST, and Tendermint Endpoints This document presents an overview of all the endpoints a node exposes: gRPC, REST as well as some other endpoints. {synopsis} @@ -22,11 +18,11 @@ The node also exposes some other endpoints, such as the Tendermint P2P endpoint, In the Cosmos SDK, Protobuf is the main [encoding](./07-encoding) library. This brings a wide range of Protobuf-based tools that can be plugged into the Cosmos SDK. One such tool is [gRPC](https://grpc.io), a modern open-source high performance RPC framework that has decent client support in several languages. -Each module exposes a [Protobuf `Query` service](../building-modules/messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: +Each module exposes a [Protobuf `Query` service](../building-modules/02-messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/server/types/app.go#L45-L47 -Note: It is not possible to expose any [Protobuf `Msg` service](../building-modules/messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programmatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../run-node/txs.html) for more information. +Note: It is not possible to expose any [Protobuf `Msg` service](../building-modules/02-messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programmatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../run-node/txs.html) for more information. The `grpc.Server` is a concrete gRPC server, which spawns and serves all gRPC query requests and a broadcast transaction request. This server can be configured inside `~/.simapp/config/app.toml`: diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/09-cli.md b/versioned_docs/version-0.46/develop/advanced-concepts/09-cli.md index 6895a486a..abac5c67b 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/09-cli.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/09-cli.md @@ -1,10 +1,6 @@ - - # Command-Line Interface -This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../basics/app-anatomy.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../building-modules/intro.md) can be found [here](../building-modules/module-interfaces.md#cli). {synopsis} +This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../high-level-concepts/app-anatomy.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../building-modules/intro.md) can be found [here](../building-modules/09-module-interfaces.md#cli). {synopsis} ## Command-Line Interface @@ -27,7 +23,7 @@ The first four strings specify the command: The next two strings are arguments: the `from_address` the user wishes to send from, the `to_address` of the recipient, and the `amount` they want to send. Finally, the last few strings of the command are optional flags to indicate how much the user is willing to pay in fees (calculated using the amount of gas used to execute the transaction and the gas prices provided by the user). -The CLI interacts with a [node](../core/node.md) to handle this command. The interface itself is defined in a `main.go` file. +The CLI interacts with a [node](../advanced-concepts/03-node.md) to handle this command. The interface itself is defined in a `main.go` file. ### Building the CLI @@ -35,7 +31,7 @@ The `main.go` file needs to have a `main()` function that creates a root command * **setting configurations** by reading in configuration files (e.g. the Cosmos SDK config file). * **adding any flags** to it, such as `--chain-id`. -* **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../core/encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. +* **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../advanced-concepts/05-encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. * **adding subcommand** for all the possible user interactions, including [transaction commands](#transaction-commands) and [query commands](#query-commands). The `main()` function finally creates an executor and [execute](https://pkg.go.dev/github.com/spf13/cobra#Command.Execute) the root command. See an example of `main()` function from the `simapp` application: @@ -52,7 +48,7 @@ Every application CLI first constructs a root command, then adds functionality b The root command (called `rootCmd`) is what the user first types into the command line to indicate which application they wish to interact with. The string used to invoke the command (the "Use" field) is typically the name of the application suffixed with `-d`, e.g. `simd` or `gaiad`. The root command typically includes the following commands to support basic functionality in the application. -* **Status** command from the Cosmos SDK rpc client tools, which prints information about the status of the connected [`Node`](../core/node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. +* **Status** command from the Cosmos SDK rpc client tools, which prints information about the status of the connected [`Node`](../advanced-concepts/03-node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. * **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/client/keys) from the Cosmos SDK client tools, which includes a collection of subcommands for using the key functions in the Cosmos SDK crypto tools, including adding a new key and saving it to the keyring, listing all public keys stored in the keyring, and deleting a key. For example, users can type `simd keys add ` to add a new key and save an encrypted copy to the keyring, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](../run-node/keyring.md). * **Server** commands from the Cosmos SDK server package. These commands are responsible for providing the mechanisms necessary to start an ABCI Tendermint application and provides the CLI framework (based on [cobra](github.com/spf13/cobra)) necessary to fully bootstrap an application. The package exposes two core functions: `StartCmd` and `ExportCmd` which creates commands to start the application and export state respectively. Click [here](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/server) to learn more. * [**Transaction**](#transaction-commands) commands. @@ -76,7 +72,7 @@ The root-level `status` and `keys` subcommands are common across most applicatio ### Transaction Commands -[Transactions](./01-transactions.md) are objects wrapping [`Msg`s](../building-modules/messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCommand` is generally added to the `rootCmd`: +[Transactions](./01-transactions.md) are objects wrapping [`Msg`s](../building-modules/02-messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCommand` is generally added to the `rootCmd`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/simapp/simd/cmd/root.go#L175-L181 @@ -84,7 +80,7 @@ This `txCommand` function adds all the transaction available to end-users for th * **Sign command** from the [`auth`](../../x/auth/spec/README.md) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, the signing command is necessary for every application. * **Broadcast command** from the Cosmos SDK client tools, to broadcast transactions. -* **All [module transaction commands](../building-modules/module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddTxCommands()` function. +* **All [module transaction commands](../building-modules/09-module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddTxCommands()` function. Here is an example of a `txCommand` aggregating these subcommands from the `simapp` application: @@ -92,7 +88,7 @@ Here is an example of a `txCommand` aggregating these subcommands from the `sima ### Query Commands -[**Queries**](../building-modules/messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of queries using the CLI interface, a function `queryCommand` is generally added to the `rootCmd`: +[**Queries**](../building-modules/02-messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of queries using the CLI interface, a function `queryCommand` is generally added to the `rootCmd`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/simapp/simd/cmd/root.go#L175-L181 @@ -102,7 +98,7 @@ This `queryCommand` function adds all the queries available to end-users for the * **Account command** from the `auth` module, which displays the state (e.g. account balance) of an account given an address. * **Validator command** from the Cosmos SDK rpc client tools, which displays the validator set of a given height. * **Block command** from the Cosmos SDK rpc client tools, which displays the block data for a given height. -* **All [module query commands](../building-modules/module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddQueryCommands()` function. +* **All [module query commands](../building-modules/09-module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddQueryCommands()` function. Here is an example of a `queryCommand` aggregating subcommands from the `simapp` application: @@ -114,7 +110,7 @@ Flags are used to modify commands; developers can include them in a `flags.go` f A _persistent_ flag (as opposed to a _local_ flag) added to a command transcends all of its children: subcommands will inherit the configured values for these flags. Additionally, all flags have default values when they are added to commands; some toggle an option off but others are empty values that the user needs to override to create valid commands. A flag can be explicitly marked as _required_ so that an error is automatically thrown if the user does not provide a value, but it is also acceptable to handle unexpected missing flags differently. -Flags are added to commands directly (generally in the [module's CLI file](../building-modules/module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `simapp` application: +Flags are added to commands directly (generally in the [module's CLI file](../building-modules/09-module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `simapp` application: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/simapp/simd/cmd/root.go#L210-L210 diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/10-events.md b/versioned_docs/version-0.46/develop/advanced-concepts/10-events.md index d11592577..032bbc3ab 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/10-events.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/10-events.md @@ -1,14 +1,10 @@ - - # Events `Event`s are objects that contain information about the execution of the application. They are mainly used by service providers like block explorers and wallet to track the execution of various messages and index transactions. {synopsis} ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {prereq} +* [Anatomy of a Cosmos SDK application](../high-level-concepts/app-anatomy.md) {prereq} * [Tendermint Documentation on Events](https://docs.tendermint.com/master/spec/abci/abci.html#events) {prereq} ## Typed Events @@ -29,7 +25,7 @@ To parse the attribute values as strings, make sure to add `'` (single quotes) a _Typed Events_ are Protobuf-defined [messages](../architecture/adr-032-typed-events.md) used by the Cosmos SDK for emitting and querying Events. They are defined in a `event.proto` file, on a **per-module basis**. -They are triggered from the module's Protobuf [`Msg` service](../building-modules/msg-services.md) +They are triggered from the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md) by using the [`EventManager`](#eventmanager), where they are read as `proto.Message`. In addition, each module documents its Events under `spec/xx_events.md`. @@ -48,8 +44,8 @@ The following examples show how to query Events using the Cosmos SDK. | Event | Description | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tx.height=23` | Query all transactions at height 23 | -| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/msg-services.md). Note the `'`s around the value. | -| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | +| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/03-msg-services.md). Note the `'`s around the value. | +| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/03-msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | | `message.module='bank'` | Query all transactions containing messages from the x/bank module. Note the `'`s around the value. | | `create_validator.validator='cosmosval1...'` | x/staking-specific Event, see [x/staking SPEC](../../../cosmos-sdk/x/staking/spec/07_events.md). | @@ -82,7 +78,7 @@ func NewHandler(keeper Keeper) sdk.Handler { switch msg := msg.(type) { ``` -See the [`Msg` services](../building-modules/msg-services.md) concept doc for a more detailed +See the [`Msg` services](../building-modules/03-msg-services.md) concept doc for a more detailed view on how to typically implement Events and use the `EventManager` in modules. ## Subscribing to Events @@ -124,7 +120,7 @@ Subscribing to this Event would be done like so: } ``` -where `ownerAddress` is an address following the [`AccAddress`](../basics/accounts.md#addresses) format. +where `ownerAddress` is an address following the [`AccAddress`](../high-level-concepts/03-accounts.md#addresses) format. ## Events (Deprecated) @@ -132,7 +128,7 @@ Previously, the Cosmos SDK supported emitting Events that were defined in `types This is why this methods as been deprecated, and replaced by _[Typed Events](#typed-events). -To learn more about the previous way of defining events, please refer to the [previous SDK documentation](https://docs.cosmos.network/v0.45/core/events.html#events-2). +To learn more about the previous way of defining events, please refer to the [previous SDK documentation](https://docs.cosmos.network/v0.45events.html#events-2). ## Next {hide} diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/11-telemetry.md b/versioned_docs/version-0.46/develop/advanced-concepts/11-telemetry.md index 0152349ec..e0606b6a4 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/11-telemetry.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/11-telemetry.md @@ -1,7 +1,3 @@ - - # Telemetry Gather relevant insights about your application and modules with custom metrics and telemetry. {synopsis} diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/12-ocap.md b/versioned_docs/version-0.46/develop/advanced-concepts/12-ocap.md index f9a84457b..8412f487d 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/12-ocap.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/12-ocap.md @@ -1,7 +1,3 @@ - - # Object-Capability Model ## Intro diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/13-runtx_middleware.md b/versioned_docs/version-0.46/develop/advanced-concepts/13-runtx_middleware.md index 8b39f127e..60e61abcf 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/13-runtx_middleware.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/13-runtx_middleware.md @@ -1,7 +1,3 @@ - - # RunTx recovery middleware `BaseApp.runTx()` function handles Go panics that might occur during transactions execution, for example, keeper has faced an invalid state and paniced. diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/13-simulation.md b/versioned_docs/version-0.46/develop/advanced-concepts/13-simulation.md index 02befbeac..327d9ac8e 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/13-simulation.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/13-simulation.md @@ -1,7 +1,3 @@ - - # Cosmos Blockchain Simulator The Cosmos SDK offers a full fledged simulation framework to fuzz test every diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/14-proto-docs.md b/versioned_docs/version-0.46/develop/advanced-concepts/14-proto-docs.md index 8ea66828c..8f4da8738 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/14-proto-docs.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/14-proto-docs.md @@ -1,7 +1,3 @@ - - # Protobuf Documentation See [Cosmos-SDK Buf Proto-docs](https://buf.build/cosmos/cosmos-sdk/docs/main) diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/15-tips.md b/versioned_docs/version-0.46/develop/advanced-concepts/15-tips.md index 1f7ef11b8..d622b2ce5 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/15-tips.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/15-tips.md @@ -1,7 +1,3 @@ - - # Transaction Tips Transaction tips are a mechanism to pay for transaction fees using another denom than the native fee denom of the chain. They are still in beta, and are not included by default in the SDK. {synopsis} diff --git a/versioned_docs/version-0.46/develop/advanced-concepts/16-upgrade.md b/versioned_docs/version-0.46/develop/advanced-concepts/16-upgrade.md index bcccd4717..a5940dafb 100644 --- a/versioned_docs/version-0.46/develop/advanced-concepts/16-upgrade.md +++ b/versioned_docs/version-0.46/develop/advanced-concepts/16-upgrade.md @@ -1,7 +1,3 @@ - - # In-Place Store Migrations ::: warning @@ -14,7 +10,7 @@ The Cosmos SDK uses two methods to perform upgrades: * Exporting the entire application state to a JSON file using the `export` CLI command, making changes, and then starting a new binary with the changed JSON file as the genesis file. -* Perform upgrades in place, which significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/upgrade.md) to set up your application modules to take advantage of in-place upgrades. +* Perform upgrades in place, which significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/13-upgrade.md) to set up your application modules to take advantage of in-place upgrades. This document provides steps to use the In-Place Store Migrations upgrade method. @@ -61,7 +57,7 @@ app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgrad }) ``` -To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../building-modules/upgrade.md). +To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../building-modules/13-upgrade.md). ### Order Of Migrations diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/app-anatomy.md b/versioned_docs/version-0.46/develop/high-level-concepts/00-overview-app.md similarity index 66% rename from versioned_docs/version-0.46/develop/high-level-concepts/app-anatomy.md rename to versioned_docs/version-0.46/develop/high-level-concepts/00-overview-app.md index 91a01b8ad..65037592b 100644 --- a/versioned_docs/version-0.46/develop/high-level-concepts/app-anatomy.md +++ b/versioned_docs/version-0.46/develop/high-level-concepts/00-overview-app.md @@ -1,14 +1,10 @@ - - # Anatomy of a Cosmos SDK Application This document describes the core parts of a Cosmos SDK application. Throughout the document, a placeholder application named `app` will be used. {synopsis} ## Node Client -The Daemon, or [Full-Node Client](../core/node.md), is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes and update their state-machine as new blocks come in. +The Daemon, or [Full-Node Client](../advanced-concepts/04-node.md), is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes and update their state-machine as new blocks come in. ```text ^ +-------------------------------+ ^ @@ -28,9 +24,9 @@ Blockchain Node | | Consensus | | v +-------------------------------+ v ``` -The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../core/node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). +The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../advanced-concepts/04-node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). -Once the main binary is built, the node can be started by running the [`start` command](../core/node.md#start-command). This command function primarily does three things: +Once the main binary is built, the node can be started by running the [`start` command](../advanced-concepts/04-node.md#start-command). This command function primarily does three things: 1. Create an instance of the state-machine defined in [`app.go`](#core-application-file). 2. Initialize the state-machine with the latest known state, extracted from the `db` stored in the `~/.app/data` folder. At this point, the state-machine is at height `appBlockHeight`. @@ -44,12 +40,12 @@ In general, the core of the state-machine is defined in a file called `app.go`. The first thing defined in `app.go` is the `type` of the application. It is generally comprised of the following parts: -* **A reference to [`baseapp`](../core/baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by Tendermint to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://docs.tendermint.com/master/spec/abci/abci.html) and the [routing logic](../core/baseapp.md#routing). -* **A list of store keys**. The [store](../core/store.md), which contains the entire state, is implemented as a [`multistore`](../core/store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. -* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../building-modules/keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. -* **A reference to an [`appCodec`](../core/encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../core/encoding.md). -* **A reference to a [`legacyAmino`](../core/encoding.md) codec.** Some parts of the Cosmos SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicity use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. -* **A reference to a [module manager](../building-modules/module-manager.md#manager)** and a [basic module manager](../building-modules/module-manager.md#basicmanager). The module manager is an object that contains a list of the application's module. It facilitates operations related to these modules, like registering their [`Msg` service](../core/baseapp.md#msg-services) and [gRPC `Query` service](../core/baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). +* **A reference to [`baseapp`](../../develop/advanced-concepts/00-baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by Tendermint to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://docs.tendermint.com/master/spec/abci/abci.html) and the [routing logic](../../develop/advanced-concepts/00-baseapp.md#routing). +* **A list of store keys**. The [store](../advanced-concepts/04-store.md), which contains the entire state, is implemented as a [`multistore`](../advanced-concepts/04-store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../advanced-concepts/ocap.md) of the Cosmos SDK. +* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. +* **A reference to an [`appCodec`](../advanced-concepts/05-encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../advanced-concepts/05-encoding.md). +* **A reference to a [`legacyAmino`](../advanced-concepts/05-encoding.md) codec.** Some parts of the Cosmos SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicity use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. +* **A reference to a [module manager](../building-modules/01-module-manager.md#manager)** and a [basic module manager](../building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's module. It facilitates operations related to these modules, like registering their [`Msg` service](../../develop/advanced-concepts/00-baseapp.md#msg-services) and [gRPC `Query` service](../../develop/advanced-concepts/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). See an example of application type definition from `simapp`, the Cosmos SDK's own app used for demo and testing purposes: @@ -57,23 +53,23 @@ See an example of application type definition from `simapp`, the Cosmos SDK's ow ### Constructor Function -This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/node.md#start-command) of the application's daemon command. +This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../advanced-concepts/04-node.md#start-command) of the application's daemon command. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/server/types/app.go#L57-L59 Here are the main actions performed by this function: -* Instantiate a new [`codec`](../core/encoding.md) and initialize the `codec` of each of the application's module using the [basic manager](../building-modules/module-manager.md#basicmanager) +* Instantiate a new [`codec`](../advanced-concepts/05-encoding.md) and initialize the `codec` of each of the application's module using the [basic manager](../building-modules/01-module-manager.md#basicmanager) * Instantiate a new application with a reference to a `baseapp` instance, a codec and all the appropriate store keys. * Instantiate all the [`keeper`s](#keeper) defined in the application's `type` using the `NewKeeper` function of each of the application's modules. Note that `keepers` must be instantiated in the correct order, as the `NewKeeper` of one module might require a reference to another module's `keeper`. -* Instantiate the application's [module manager](../building-modules/module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. -* With the module manager, initialize the application's [`Msg` services](../core/baseapp.md#msg-services), [gRPC `Query` services](../core/baseapp.md#grpc-query-services), [legacy `Msg` routes](../core/baseapp.md#routing) and [legacy query routes](../core/baseapp.md#query-routing). When a transaction is relayed to the application by Tendermint via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The Cosmos SDK still supports legacy `Msg`s and legacy Tendermint queries, which are routed using respectively the legacy `Msg` routes and the legacy query routes. -* With the module manager, register the [application's modules' invariants](../building-modules/invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../building-modules/invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry will be triggered (usually the chain is halted). This is useful to make sure no critical bug goes unnoticed and produces long-lasting effects that would be hard to fix. +* Instantiate the application's [module manager](../../integrate/building-modules/01-module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. +* With the module manager, initialize the application's [`Msg` services](../../develop/advanced-concepts/00-baseapp.md#msg-services), [gRPC `Query` services](../../develop/advanced-concepts/00-baseapp.md#grpc-query-services), [legacy `Msg` routes](../../develop/advanced-concepts/00-baseapp.md#routing) and [legacy query routes](../../develop/advanced-concepts/00-baseapp.md#query-routing). When a transaction is relayed to the application by Tendermint via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The Cosmos SDK still supports legacy `Msg`s and legacy Tendermint queries, which are routed using respectively the legacy `Msg` routes and the legacy query routes. +* With the module manager, register the [application's modules' invariants](../../integrate/building-modules/07-invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../../integratebuilding-modules/07-invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry will be triggered (usually the chain is halted). This is useful to make sure no critical bug goes unnoticed and produces long-lasting effects that would be hard to fix. * With the module manager, set the order of execution between the `InitGenesis`, `BeginBlocker` and `EndBlocker` functions of each of the [application's modules](#application-module-interface). Note that not all modules implement these functions. * Set the remainder of application's parameters: * [`InitChainer`](#initchainer): used to initialize the application when it is first started. * [`BeginBlocker`, `EndBlocker`](#beginblocker-and-endlbocker): called at the beginning and the end of every block). - * [`anteHandler`](../core/baseapp.md#antehandler): used to handle fees and signature verification. + * [`anteHandler`](../../develop/advanced-concepts/00-baseapp.md#antehandler): used to handle fees and signature verification. * Mount the stores. * Return the application. @@ -87,7 +83,7 @@ See an example of application constructor from `simapp`: The `InitChainer` is a function that initializes the state of the application from a genesis file (i.e. token balances of genesis accounts). It is called when the application receives the `InitChain` message from the Tendermint engine, which happens when the node is started at `appBlockHeight == 0` (i.e. on genesis). The application must set the `InitChainer` in its [constructor](#constructor-function) via the [`SetInitChainer`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetInitChainer) method. -In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn will call the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../building-modules/module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#application-constructor), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. +In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../../integrate/building-modules/08-genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn will call the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../../integrate/building-modules/01-module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#application-constructor), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. See an example of an `InitChainer` from `simapp`: @@ -97,7 +93,7 @@ See an example of an `InitChainer` from `simapp`: The Cosmos SDK offers developers the possibility to implement automatic execution of code as part of their application. This is implemented through two function called `BeginBlocker` and `EndBlocker`. They are called when the application receives respectively the `BeginBlock` and `EndBlock` messages from the Tendermint engine, which happens at the beginning and at the end of each block. The application must set the `BeginBlocker` and `EndBlocker` in its [constructor](#constructor-function) via the [`SetBeginBlocker`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetBeginBlocker) and [`SetEndBlocker`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetEndBlocker) methods. -In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../building-modules/beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn will call the `BeginBlock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BeginBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods respectively. This is done via the [module manager](../building-modules/module-manager.md) in the [application's constructor](#application-constructor), and the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. +In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../../integratebuilding-modules/beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn will call the `BeginBlock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BeginBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods respectively. This is done via the [module manager](../../integrate/building-modules/01-module-manager.md) in the [application's constructor](#application-constructor), and the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in `BeginBlocker` or `EndBlocker`, and must also be careful not to make them too computationally expensive, as [gas](./gas-fees.md) does not constrain the cost of `BeginBlocker` and `EndBlocker` execution. @@ -115,9 +111,9 @@ Here are descriptions of what each of the four fields means: * `InterfaceRegistry`: The `InterfaceRegistry` is used by the Protobuf codec to handle interfaces that are encoded and decoded (we also say "unpacked") using [`google.protobuf.Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). `Any` could be thought as a struct that contains a `type_url` (name of a concrete type implementing the interface) and a `value` (its encoded bytes). `InterfaceRegistry` provides a mechanism for registering interfaces and implementations that can be safely unpacked from `Any`. Each of the application's modules implements the `RegisterInterfaces` method that can be used to register the module's own interfaces and implementations. * You can read more about Any in [ADR-19](../architecture/adr-019-protobuf-state-encoding.md#usage-of-any-to-encode-interfaces). - * To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/gogo/protobuf). By default, the [gogo protobuf implementation of `Any`](https://pkg.go.dev/github.com/gogo/protobuf/types) uses [global type registration](https://github.com/gogo/protobuf/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). + * To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/gogo/protobuf). By default, the [gogo protobuf implementation of `Any`](https://pkg.go.dev/github.com/gogo/protobuf/types) uses [global type registration](https://github.com/gogo/protobuf/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../../integrate/architecture/adr-019-protobuf-state-encoding.md). * `Codec`: the default codec used throughout the Cosmos SDK. It is composed of a `BinaryCodec` used to encode and decode state, and a `JSONCodec` used to output data to the users (for example in the [CLI](#cli)). By default, the SDK uses Protobuf as `Codec`. -* `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/transactions.md). +* `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../advanced-concepts/01-transactions.md). * `Amino`: Some legacy parts of the Cosmos SDK still use Amino for backwards-compatibility. Each module exposes a `RegisterLegacyAmino` method to register the module's specific types within Amino. This `Amino` codec should not be used by app developers anymore, and will be removed in future releases. The Cosmos SDK exposes a `MakeTestEncodingConfig` function used to create a `EncodingConfig` for the app constructor (`NewApp`). It uses Protobuf as a default `Codec`. @@ -130,19 +126,19 @@ See an example of a `MakeTestEncodingConfig` from `simapp`: ## Modules -[Modules](../building-modules/intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying Tendermint engine via the ABCI to the application, it is routed by [`baseapp`](../core/baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). +[Modules](../building-modules/intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying Tendermint engine via the ABCI to the application, it is routed by [`baseapp`](../../develop/advanced-concepts/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). ### Application Module Interface -Modules must implement [interfaces](../building-modules/module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../building-modules/module-manager.md#appmodulebasic) and [`AppModule`](../building-modules/module-manager.md#appmodule). The former implements basic non-dependent elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are, by convention, defined in a file called `module.go`. +Modules must implement [interfaces](../../integratebuilding-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../../integrate/building-modules/01-module-manager.md#appmodulebasic) and [`AppModule`](../../integrate/building-modules/01-module-manager.md#appmodule). The former implements basic non-dependent elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are, by convention, defined in a file called `module.go`. -`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the [`module manager`](../building-modules/module-manager.md#manager), which manages the application's collection of modules. +`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the [`module manager`](../building-modules/01-module-manager.md#manager), which manages the application's collection of modules. ### `Msg` Services Each module defines two [Protobuf services](https://developers.google.com/protocol-buffers/docs/proto#services): one `Msg` service to handle messages, and one gRPC `Query` service to handle queries. If we consider the module as a state-machine, then a `Msg` service is a set of state transition RPC methods. Each Protobuf `Msg` service method is 1:1 related to a Protobuf request type, which must implement `sdk.Msg` interface. -Note that `sdk.Msg`s are bundled in [transactions](../core/transactions.md), and each transaction contains one or multiple messages. +Note that `sdk.Msg`s are bundled in [transactions](../high-level-concepts/01-tx-lifecycle.md), and each transaction contains one or multiple messages. When a valid block of transactions is received by the full-node, Tendermint relays each one to the application via [`DeliverTx`](https://docs.tendermint.com/master/spec/abci/apps.html#delivertx). Then, the application handles the transaction: @@ -151,7 +147,7 @@ When a valid block of transactions is received by the full-node, Tendermint rela 3. `sdk.Msg`s are encoded using Protobuf [`Any`s](#register-codec). By analyzing each `Any`'s `type_url`, baseapp's `msgServiceRouter` routes the `sdk.Msg` to the corresponding module's `Msg` service. 4. If the message is successfully processed, the state is updated. -For a more details look at a transaction [lifecycle](./tx-lifecycle.md). +For a more details look at a transaction [lifecycle](./01-tx-lifecycle.md). Module developers create custom `Msg` services when they build their own module. The general practice is to define the `Msg` Protobuf service in a `tx.proto` file. For example, the `x/bank` module defines a service with two methods to transfer tokens: @@ -163,7 +159,7 @@ Each module should also implement the `RegisterServices` method as part of the [ ### gRPC `Query` Services -gRPC `Query` services allows users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configured under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml). +gRPC `Query` services allows users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configured under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../../user/run-node.md#configuring-the-node-using-apptoml). gRPC `Query` services are defined in the module's Protobuf definition files, specifically inside `query.proto`. The `query.proto` definition file exposes a single `Query` [Protobuf service](https://developers.google.com/protocol-buffers/docs/proto#services). Each gRPC query endpoint corresponds to a service method, starting with the `rpc` keyword, inside the `Query` service. @@ -173,7 +169,7 @@ Finally, each module should also implement the `RegisterServices` method as part ### Keeper -[`Keepers`](../building-modules/keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../core/ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). +[`Keepers`](../../integratebuilding-modules/06-keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../advanced-concepts/12-ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). `Keepers` are generally defined in a file called `keeper.go`. It contains the `keeper`'s type definition and methods. @@ -191,10 +187,10 @@ Each module defines command-line commands, gRPC services and REST routes to be e #### CLI -Generally, the [commands related to a module](../building-modules/module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands in two category, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go` respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): +Generally, the [commands related to a module](../building-modules/09-module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands in two category, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go` respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): * Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each [message type](#message-types) defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The Cosmos SDK handles signing and the addition of other transaction metadata. -* Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../core/baseapp.md#query-routing), which routes them to the appropriate [querier](#querier) the `queryRoute` parameter supplied. +* Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../../develop/advanced-concepts/00-baseapp.md#query-routing), which routes them to the appropriate [querier](#querier) the `queryRoute` parameter supplied. #### gRPC @@ -217,7 +213,7 @@ The Cosmos SDK also provides a development endpoint to generate [Swagger](https: [Interfaces](#command-line-grpc-services-and-rest-interfaces) let end-users interact with full-node clients. This means querying data from the full-node or creating and sending new transactions to be relayed by the full-node and eventually included in a block. -The main interface is the [Command-Line Interface](../core/cli.md). The CLI of a Cosmos SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and defined in a file called `appd/main.go`. The file contains: +The main interface is the [Command-Line Interface](../01-tx-lifecycle.md06-cli.md). The CLI of a Cosmos SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and defined in a file called `appd/main.go`. The file contains: * **A `main()` function**, which is executed to build the `appd` interface client. This function prepares each command and adds them to the `rootCmd` before building them. At the root of `appd`, the function adds generic commands like `status`, `keys` and `config`, query commands, tx commands and `rest-server`. * **Query commands** are added by calling the `queryCmd` function. This function returns a Cobra command that contains the query commands defined in each of the application's modules (passed as an array of `sdk.ModuleClients` from the `main()` function), as well as some other lower level query commands such as block or validator queries. Query command are called by using the command `appd query [query]` of the CLI. @@ -253,4 +249,4 @@ Here is an example of the [Cosmos Hub Makefile](https://github.com/cosmos/gaia/b ## Next {hide} -Learn more about the [Lifecycle of a transaction](./tx-lifecycle.md) {hide} +Learn more about the [Lifecycle of a transaction](./01-tx-lifecycle.md) {hide} diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/tx-lifecycle.md b/versioned_docs/version-0.46/develop/high-level-concepts/01-tx-lifecycle.md similarity index 79% rename from versioned_docs/version-0.46/develop/high-level-concepts/tx-lifecycle.md rename to versioned_docs/version-0.46/develop/high-level-concepts/01-tx-lifecycle.md index efb59e1a0..6a4f040a6 100644 --- a/versioned_docs/version-0.46/develop/high-level-concepts/tx-lifecycle.md +++ b/versioned_docs/version-0.46/develop/high-level-concepts/01-tx-lifecycle.md @@ -1,10 +1,6 @@ - - # Transaction Lifecycle -This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../core/transactions.md). The transaction will be referred to as `Tx`. {synopsis} +This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../advanced-concepts/01-transactions.md). The transaction will be referred to as `Tx`. {synopsis} ## Pre-requisite Readings @@ -14,7 +10,7 @@ This document describes the lifecycle of a transaction from creation to committe ### Transaction Creation -One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../core/cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: +One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../advanced-concepts/06-cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: ```bash [appname] tx [command] [args] [flags] @@ -22,11 +18,11 @@ One of the main application interfaces is the command-line interface. The transa This command will automatically **create** the transaction, **sign** it using the account's private key, and **broadcast** it to the specified peer node. -There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](./accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds will be drawn from the specified `from` address. +There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](./03-accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds will be drawn from the specified `from` address. #### Gas and Fees -Additionally, there are several [flags](../core/cli.md) users can use to indicate how much they are willing to pay in [fees](./gas-fees.md): +Additionally, there are several [flags](../advanced-concepts/06-cli.md) users can use to indicate how much they are willing to pay in [fees](./gas-fees.md): * `--gas` refers to how much [gas](./gas-fees.md), which represents computational resources, `Tx` consumes. Gas is dependent on the transaction and is not precisely calculated until execution, but can be estimated by providing `auto` as the value for `--gas`. * `--gas-adjustment` (optional) can be used to scale `gas` up in order to avoid underestimating. For example, users can specify their gas adjustment as 1.5 to use 1.5 times the estimated gas. @@ -48,7 +44,7 @@ appd tx send 1000uatom --from --gas auto --ga #### Other Transaction Creation Methods -The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../core/grpc_rest.md) or some other entry point defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). +The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../advanced-concepts/08-grpc_rest.md) or some other entry point defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). ## Addition to Mempool @@ -68,7 +64,7 @@ are not empty, enforcing nonnegative numbers, and other logic specified in the d **_Stateful_** checks validate transactions and messages based on a committed state. Examples include checking that the relevant values exist and can be transacted with, the address has sufficient funds, and the sender is authorized or has the correct ownership to transact. -At any given moment, full-nodes typically have [multiple versions](../core/baseapp.md#state-updates) +At any given moment, full-nodes typically have [multiple versions](../../develop/advanced-concepts/00-baseapp.md#state-updates) of the application's internal state for different purposes. For example, nodes will execute state changes while in the process of verifying transactions, but still need a copy of the last committed state in order to answer queries - they should not respond using state with uncommitted changes. @@ -79,12 +75,12 @@ through several steps, beginning with decoding `Tx`. ### Decoding -When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../core/encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../core/baseapp.md#runtx-antehandler-runmsgs-posthandler) function is called to run in `runTxModeCheck` mode, meaning the function will run all checks but exit before executing messages and writing state changes. +When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../advanced-concepts/05-encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../../develop/advanced-concepts/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) function is called to run in `runTxModeCheck` mode, meaning the function will run all checks but exit before executing messages and writing state changes. ### ValidateBasic -Messages ([`sdk.Msg`](../core/transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. -To discard obviously invalid messages, the `BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../core/baseapp.md#checktx) and [`DeliverTx`](../core/baseapp.md#delivertx) transactions. +Messages ([`sdk.Msg`](../advanced-concepts/01-transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. +To discard obviously invalid messages, the `BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../../develop/advanced-concepts/00-baseapp.md#checktx) and [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx) transactions. `ValidateBasic` can include only **stateless** checks (the checks that do not require access to the state). #### Guideline @@ -94,7 +90,7 @@ Other validation operations must be performed when [handling a message](../build Example, if the message is to send coins from one address to another, `ValidateBasic` likely checks for non-empty addresses and a non-negative coin amount, but does not require knowledge of state such as the account balance of an address. -See also [Msg Service Validation](../building-modules/msg-services.md#Validation). +See also [Msg Service Validation](../building-modules/03-msg-services.md#Validation). ### AnteHandler @@ -106,7 +102,7 @@ For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/ ### Gas -The [`Context`](../core/context.md), which keeps a `GasMeter` that will track how much gas has been used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed so during execution, ever exceeds `GasWanted`, the execution will stop and the changes made to the cached copy of the state won't be committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. +The [`Context`](../advanced-concepts/02-context.md), which keeps a `GasMeter` that will track how much gas has been used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed so during execution, ever exceeds `GasWanted`, the execution will stop and the changes made to the cached copy of the state won't be committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. ### Discard or Addition to Mempool @@ -192,10 +188,10 @@ explicitly ordered in the block proposal. ### DeliverTx -The `DeliverTx` ABCI function defined in [`BaseApp`](../core/baseapp.md) does the bulk of the +The `DeliverTx` ABCI function defined in [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md) does the bulk of the state transitions: it is run for each transaction in the block in sequential order as committed to during consensus. Under the hood, `DeliverTx` is almost identical to `CheckTx` but calls the -[`runTx`](../core/baseapp.md#runtx) function in deliver mode instead of check mode. +[`runTx`](../../develop/advanced-concepts/00-baseapp.md#runtx) function in deliver mode instead of check mode. Instead of using their `checkState`, full-nodes use `deliverState`: * **Decoding:** Since `DeliverTx` is an ABCI call, `Tx` is received in the encoded `[]byte` form. @@ -208,14 +204,14 @@ Instead of using their `checkState`, full-nodes use `deliverState`: to each node - differing values across nodes would yield nondeterministic results. * **`MsgServiceRouter`:** While `CheckTx` would have exited, `DeliverTx` continues to run - [`runMsgs`](../core/baseapp.md#runtx-antehandler-runmsgs-posthandler) to fully execute each `Msg` within the transaction. + [`runMsgs`](../../develop/advanced-concepts/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) to fully execute each `Msg` within the transaction. Since the transaction may have messages from different modules, `BaseApp` needs to know which module - to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/msg-services.md). - For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/msg-services.md#handler-type) within the module. + to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). + For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/01-module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/03-msg-services.md#handler-type) within the module. * **`Msg` service:** Protobuf `Msg` service is responsible for executing each message in the `Tx` and causes state transitions to persist in `deliverTxState`. -* **PostHandlers:** [`PostHandler`](../core/baseapp.md#posthandler)s run after the execution of the message. If they fail, the state change of `runMsgs`, as well of `PostHandlers` are both reverted. +* **PostHandlers:** [`PostHandler`](../../develop/advanced-concepts/00-baseapp.md#posthandler)s run after the execution of the message. If they fail, the state change of `runMsgs`, as well of `PostHandlers` are both reverted. * **Gas:** While a `Tx` is being delivered, a `GasMeter` is used to keep track of how much gas is being used; if execution completes, `GasUsed` is set and returned in the @@ -236,8 +232,8 @@ not they should commit the state changes. When they receive enough validator votes (2/3+ _precommits_ weighted by voting power), full nodes commit to a new block to be added to the blockchain and finalize the state transitions in the application layer. A new state root is generated to serve as -a merkle proof for the state transitions. Applications use the [`Commit`](../core/baseapp.md#commit) -ABCI method inherited from [Baseapp](../core/baseapp.md); it syncs all the state transitions by +a merkle proof for the state transitions. Applications use the [`Commit`](../../develop/advanced-concepts/00-baseapp.md#commit) +ABCI method inherited from [Baseapp](../../develop/advanced-concepts/00-baseapp.md); it syncs all the state transitions by writing the `deliverState` into the application's internal state. As soon as the state changes are committed, `checkState` start afresh from the most recently committed state and `deliverState` resets to `nil` in order to be consistent and reflect the changes. @@ -254,4 +250,4 @@ in `[]byte` form, is stored in a block and appended to the blockchain. ## Next {hide} -Learn about [accounts](./accounts.md) {hide} +Learn about [accounts](./03-accounts.md) {hide} diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/query-lifecycle.md b/versioned_docs/version-0.46/develop/high-level-concepts/02-query-lifecycle.md similarity index 67% rename from versioned_docs/version-0.46/develop/high-level-concepts/query-lifecycle.md rename to versioned_docs/version-0.46/develop/high-level-concepts/02-query-lifecycle.md index 80b492f57..757cb47d8 100644 --- a/versioned_docs/version-0.46/develop/high-level-concepts/query-lifecycle.md +++ b/versioned_docs/version-0.46/develop/high-level-concepts/02-query-lifecycle.md @@ -1,18 +1,14 @@ - - # Query Lifecycle This document describes the lifecycle of a query in a Cosmos SDK application, from the user interface to application stores and back. {synopsis} ## Pre-requisite Readings -* [Transaction Lifecycle](./tx-lifecycle.md) {prereq} +* [Transaction Lifecycle](./01-tx-lifecycle.md) {prereq} ## Query Creation -A [**query**](../building-modules/messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../core/transactions.md) (view the lifecycle [here](./tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. +A [**query**](../building-modules/02-messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../advanced-concepts/01-transactions.md) (view the lifecycle [here](./01-tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. For the purpose of explaining the query lifecycle, let's say `MyQuery` is requesting a list of delegations made by a certain delegator address in the application called `simapp`. As to be expected, the [`staking`](../../x/staking/spec/README.md) module handles this query. But first, there are a few ways `MyQuery` can be created by users. @@ -34,9 +30,9 @@ simd query [moduleName] [command] --flag To provide values such as `--node` (the full-node the CLI connects to), the user can use the [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) config file to set them or provide them as flags. -The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../core/cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. +The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../advanced-concepts/06-cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. -Another interface through which users can make queries is [gRPC](https://grpc.io) requests to a [gRPC server](../core/grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. +Another interface through which users can make queries is [gRPC](https://grpc.io) requests to a [gRPC server](../advanced-concepts/08-grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. One such tool is [grpcurl](https://github.com/fullstorydev/grpcurl), and a gRPC request for `MyQuery` using this client looks like: @@ -52,7 +48,7 @@ grpcurl \ ### REST -Another interface through which users can make queries is through HTTP Requests to a [REST server](../core/grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). +Another interface through which users can make queries is through HTTP Requests to a [REST server](../advanced-concepts/08-grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). An example HTTP request for `MyQuery` looks like: @@ -68,10 +64,10 @@ The examples above show how an external user can interact with a node by queryin The first thing that is created in the execution of a CLI command is a `client.Context`. A `client.Context` is an object that stores all the data needed to process a request on the user side. In particular, a `client.Context` stores the following: -* **Codec**: The [encoder/decoder](../core/encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. +* **Codec**: The [encoder/decoder](../advanced-concepts/05-encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. * **Account Decoder**: The account decoder from the [`auth`](../../x/auth/spec/README.md) module, which translates `[]byte`s into accounts. * **RPC Client**: The Tendermint RPC Client, or node, to which the request will be relayed to. -* **Keyring**: A [Key Manager](../basics/accounts.md#keyring) used to sign transactions and handle other operations with keys. +* **Keyring**: A [Key Manager](../high-level-concepts/03-accounts.md#keyring) used to sign transactions and handle other operations with keys. * **Output Writer**: A [Writer](https://pkg.go.dev/io/#Writer) used to output the response. * **Configurations**: The flags configured by the user for this command, including `--height`, specifying the height of the blockchain to query and `--indent`, which indicates to add an indent to the JSON response. @@ -87,7 +83,7 @@ At this point in the lifecycle, the user has created a CLI command with all of t #### Encoding -In our case (querying an address's delegations), `MyQuery` contains an [address](./accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. +In our case (querying an address's delegations), `MyQuery` contains an [address](./03-accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. Here is what the code looks like for the CLI command: @@ -99,7 +95,7 @@ The Cosmos SDK leverages code generated from Protobuf services to make queries. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/staking/client/cli/query.go#L317-L341 -Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../core/node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. +Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../advanced-concepts/03-node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. Here is what the code looks like: @@ -107,17 +103,17 @@ Here is what the code looks like: ## RPC -With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../core/encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. +With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../advanced-concepts/05-encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. Read more about ABCI Clients and Tendermint RPC in the [Tendermint documentation](https://docs.tendermint.com/master/rpc/). ## Application Query Handling -When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../core/baseapp.md) implements the ABCI [`Query()`](../core/baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` will relay the request to the relevant module. +When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../../develop/advanced-concepts/00-baseapp.md) implements the ABCI [`Query()`](../../develop/advanced-concepts/00-baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` will relay the request to the relevant module. -Apart from gRPC routes, `baseapp` also handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [legacy queriers](../building-modules/query-services.md#legacy-queriers). To learn more about these queries, please refer to [this guide](../core/grpc_rest.md#tendermint-rpc). +Apart from gRPC routes, `baseapp` also handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [legacy queriers](../building-modules/04-query-services.md#legacy-queriers). To learn more about these queries, please refer to [this guide](../advanced-concepts/08-grpc_rest.md#tendermint-rpc). -Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/query-services.md). +Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/04-query-services.md). Once a result is received from the querier, `baseapp` begins the process of returning a response to the user. @@ -127,7 +123,7 @@ Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci ### CLI Response -The application [`codec`](../core/encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). +The application [`codec`](../advanced-concepts/05-encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/client/context.go#L315-L343 @@ -135,4 +131,4 @@ And that's a wrap! The result of the query is outputted to the console by the CL ## Next {hide} -Read more about [accounts](./accounts.md). {hide} +Read more about [accounts](./03-accounts.md). {hide} diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/accounts.md b/versioned_docs/version-0.46/develop/high-level-concepts/03-accounts.md similarity index 96% rename from versioned_docs/version-0.46/develop/high-level-concepts/accounts.md rename to versioned_docs/version-0.46/develop/high-level-concepts/03-accounts.md index dde895cce..97b32f914 100644 --- a/versioned_docs/version-0.46/develop/high-level-concepts/accounts.md +++ b/versioned_docs/version-0.46/develop/high-level-concepts/03-accounts.md @@ -1,7 +1,3 @@ - - # Accounts This document describes the in-built account and public key system of the Cosmos SDK. {synopsis} @@ -12,7 +8,7 @@ This document describes the in-built account and public key system of the Cosmos ## Account Definition -In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. +In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/02-messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The BIP32 allows users to create an HD wallet (as specified in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. A single seed can derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. @@ -137,7 +133,7 @@ The default implementation of `Keyring` comes from the third-party [`99designs/k A few notes on the `Keyring` methods: -* `Sign(uid string, msg []byte) ([]byte, types.PubKey, error)` strictly deals with the signature of the `msg` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). +* `Sign(uid string, msg []byte) ([]byte, types.PubKey, error)` strictly deals with the signature of the `msg` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`anteHandler`](../../develop/advanced-concepts/00-baseapp.md#antehandler). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L48-L65 * `NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (*Record, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring: diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/gas-fees.md b/versioned_docs/version-0.46/develop/high-level-concepts/04-gas-fees.md similarity index 69% rename from versioned_docs/version-0.46/develop/high-level-concepts/gas-fees.md rename to versioned_docs/version-0.46/develop/high-level-concepts/04-gas-fees.md index b49bc8a97..ffdab45bc 100644 --- a/versioned_docs/version-0.46/develop/high-level-concepts/gas-fees.md +++ b/versioned_docs/version-0.46/develop/high-level-concepts/04-gas-fees.md @@ -1,7 +1,3 @@ - - # Gas and Fees This document describes the default strategies to handle gas and fees within a Cosmos SDK application. {synopsis} @@ -15,7 +11,7 @@ This document describes the default strategies to handle gas and fees within a C In the Cosmos SDK, `gas` is a special unit that is used to track the consumption of resources during execution. `gas` is typically consumed whenever read and writes are made to the store, but it can also be consumed if expensive computation needs to be done. It serves two main purposes: * Make sure blocks are not consuming too many resources and will be finalized. This is implemented by default in the Cosmos SDK via the [block gas meter](#block-gas-meter). -* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`AnteHandler`](#antehandler). +* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/02-messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`AnteHandler`](#antehandler). ## Gas Meter @@ -34,7 +30,7 @@ where: * `IsPastLimit()` returns `true` if the amount of gas consumed by the gas meter instance is strictly above the limit, `false` otherwise. * `IsOutOfGas()` returns `true` if the amount of gas consumed by the gas meter instance is above or equal to the limit, `false` otherwise. -The gas meter is generally held in [`ctx`](../core/context.md), and consuming gas is done with the following pattern: +The gas meter is generally held in [`ctx`](../advanced-concepts/02-context.md), and consuming gas is done with the following pattern: ```go ctx.GasMeter().ConsumeGas(amount, "description") @@ -44,17 +40,17 @@ By default, the Cosmos SDK makes use of two different gas meters, the [main gas ### Main Gas Meter -`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../core/baseapp.md#beginblock), [`DeliverTx`](../core/baseapp.md#delivertx) and [`EndBlock`](../core/baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. +`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock), [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx) and [`EndBlock`](../../develop/advanced-concepts/00-baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. -Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) or [`Msg` service](../building-modules/msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../core/store.md#gaskv-store). +Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) or [`Msg` service](../building-modules/03-msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../advanced-concepts/04-store.md#gaskv-store). ### Block Gas Meter -`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../core/baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default, Cosmos SDK applications use the default consensus parameters provided by Tendermint: +`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default, Cosmos SDK applications use the default consensus parameters provided by Tendermint: +++ https://github.com/tendermint/tendermint/blob/v0.35.4/types/params.go#L78-L117 -When a new [transaction](../core/transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: +When a new [transaction](../advanced-concepts/01-transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: ```go ctx.BlockGasMeter().ConsumeGas( @@ -73,13 +69,13 @@ The anteHandler is not implemented in the core Cosmos SDK but in a module. That +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/types/tx_msg.go#L38-L46 This enables developers to play with various types for the transaction of their application. In the default `auth` module, the default transaction type is `Tx`: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L13-L26 -* Verify signatures for each [`message`](../building-modules/messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. +* Verify signatures for each [`message`](../building-modules/02-messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. * During `CheckTx`, verify that the gas prices provided with the transaction is greater than the local `min-gas-prices` (as a reminder, gas-prices can be deducted from the following equation: `fees = gas * gas-prices`). `min-gas-prices` is a parameter local to each full-node and used during `CheckTx` to discard transactions that do not provide a minimum amount of fees. This ensures that the mempool cannot be spammed with garbage transactions. * Verify that the sender of the transaction has enough funds to cover for the `fees`. When the end-user generates a transaction, they must indicate 2 of the 3 following parameters (the third one being implicit): `fees`, `gas` and `gas-prices`. This signals how much they are willing to pay for nodes to execute their transaction. The provided `gas` value is stored in a parameter called `GasWanted` for later use. * Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is crucial**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx` is set to `newCtx` after `anteHandler` is run, and the `anteHandler` is run each time `DeliverTx` is called). -As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../core/baseapp.md#delivertx) returns. +As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx) returns. ## Next {hide} -Learn about [baseapp](../core/baseapp.md) {hide} +Learn about [baseapp](../../develop/advanced-concepts/00-baseapp.md) {hide} diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/README.md b/versioned_docs/version-0.46/develop/high-level-concepts/README.md deleted file mode 100644 index 3907f6e60..000000000 --- a/versioned_docs/version-0.46/develop/high-level-concepts/README.md +++ /dev/null @@ -1,17 +0,0 @@ - - -# Basics - -This repository contains reference documentation on the basic concepts of the Cosmos SDK. - -1. [Anatomy of a Cosmos SDK Application](./app-anatomy.md) -2. [Lifecycle of a transaction](./tx-lifecycle.md) -3. [Lifecycle of a query](./query-lifecycle.md) -4. [Accounts](./accounts.md) -5. [Gas and Fees](./gas-fees.md) - -After reading the basics, head on to the [Core Reference](../core/README.md) for more advanced material. diff --git a/versioned_docs/version-0.46/develop/high-level-concepts/_category_.json b/versioned_docs/version-0.46/develop/high-level-concepts/_category_.json new file mode 100644 index 000000000..2c4105ee6 --- /dev/null +++ b/versioned_docs/version-0.46/develop/high-level-concepts/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "High Level Concepts", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/develop/intro/overview.md b/versioned_docs/version-0.46/develop/intro/00-what-is-sdk.md similarity index 97% rename from versioned_docs/version-0.46/develop/intro/overview.md rename to versioned_docs/version-0.46/develop/intro/00-what-is-sdk.md index 859f0acce..beb2ba555 100644 --- a/versioned_docs/version-0.46/develop/intro/overview.md +++ b/versioned_docs/version-0.46/develop/intro/00-what-is-sdk.md @@ -1,14 +1,8 @@ - - -# High-level Overview - -## What is the Cosmos SDK +# What is the Cosmos SDK The [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is an open-source framework for building multi-asset public Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as permissioned Proof-of-Authority (PoA) blockchains. Blockchains built with the Cosmos SDK are generally referred to as **application-specific blockchains**. -The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the Cosmos SDK as the npm-like framework to build secure blockchain applications on top of [Tendermint](https://github.com/tendermint/tendermint). SDK-based blockchains are built out of composable [modules](../building-modules/intro.md), most of which are open-source and readily available for any developers to use. Anyone can create a module for the Cosmos SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system that allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [Object-Capability Model](../core/ocap.md). +The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the Cosmos SDK as the npm-like framework to build secure blockchain applications on top of [Tendermint](https://github.com/tendermint/tendermint). SDK-based blockchains are built out of composable [modules](../building-modules/intro.md), most of which are open-source and readily available for any developers to use. Anyone can create a module for the Cosmos SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system that allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [Object-Capability Model](../advanced-concepts/ocap.md). ## What are Application-Specific Blockchains diff --git a/versioned_docs/version-0.46/develop/intro/why-app-specific.md b/versioned_docs/version-0.46/develop/intro/01-why-app-specific.md similarity index 99% rename from versioned_docs/version-0.46/develop/intro/why-app-specific.md rename to versioned_docs/version-0.46/develop/intro/01-why-app-specific.md index 91e84ce0c..3222f5b31 100644 --- a/versioned_docs/version-0.46/develop/intro/why-app-specific.md +++ b/versioned_docs/version-0.46/develop/intro/01-why-app-specific.md @@ -1,7 +1,3 @@ - - # Application-Specific Blockchains This document explains what application-specific blockchains are, and why developers would want to build one as opposed to writing Smart Contracts. {synopsis} diff --git a/versioned_docs/version-0.46/develop/intro/sdk-app-architecture.md b/versioned_docs/version-0.46/develop/intro/02-sdk-app-architecture.md similarity index 91% rename from versioned_docs/version-0.46/develop/intro/sdk-app-architecture.md rename to versioned_docs/version-0.46/develop/intro/02-sdk-app-architecture.md index 7a1113683..626c02fc4 100644 --- a/versioned_docs/version-0.46/develop/intro/sdk-app-architecture.md +++ b/versioned_docs/version-0.46/develop/intro/02-sdk-app-architecture.md @@ -1,7 +1,3 @@ - - # Blockchain Architecture ## State machine @@ -84,8 +80,8 @@ Note that **Tendermint only handles transaction bytes**. It has no knowledge of Here are the most important messages of the ABCI: -* `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. . A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. -* `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again, along with the actual [`Msg` service](../building-modules/msg-services.md) RPC for each message in the transaction. +* `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. . A special handler called the [`AnteHandler`](../high-level-concepts/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +* `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again, along with the actual [`Msg` service](../building-modules/03-msg-services.md) RPC for each message in the transaction. * `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transactions or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/v0.35/introduction/what-is-tendermint.html#abci-overview). diff --git a/versioned_docs/version-0.46/develop/intro/sdk-design.md b/versioned_docs/version-0.46/develop/intro/03-sdk-design.md similarity index 82% rename from versioned_docs/version-0.46/develop/intro/sdk-design.md rename to versioned_docs/version-0.46/develop/intro/03-sdk-design.md index e9f61be4e..7d9d81654 100644 --- a/versioned_docs/version-0.46/develop/intro/sdk-design.md +++ b/versioned_docs/version-0.46/develop/intro/03-sdk-design.md @@ -1,10 +1,6 @@ - - # Main Components of the Cosmos SDK -The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of Tendermint. At its core, the Cosmos SDK is a boilerplate implementation of the [ABCI](./sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../core/store.md#multistore) to persist data and a [`router`](../core/baseapp.md#routing) to handle transactions. +The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of Tendermint. At its core, the Cosmos SDK is a boilerplate implementation of the [ABCI](./sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../advanced-concepts/04-store.md#multistore) to persist data and a [`router`](../advanced-concepts/00-baseapp.md#routing) to handle transactions. Here is a simplified view of how transactions are handled by an application built on top of the Cosmos SDK when transferred from Tendermint via `DeliverTx`: @@ -15,7 +11,7 @@ Here is a simplified view of how transactions are handled by an application buil ## `baseapp` -`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../basics/app-anatomy.md#core-application-file). +`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../high-level-concepts/00-overview-app.md#core-application-file). Here is an example of this from `simapp`, the Cosmos SDK demonstration app: @@ -23,13 +19,13 @@ Here is an example of this from `simapp`, the Cosmos SDK demonstration app: The goal of `baseapp` is to provide a secure interface between the store and the extensible state machine while defining as little about the state machine as possible (staying true to the ABCI). -For more on `baseapp`, please click [here](../core/baseapp.md). +For more on `baseapp`, please click [here](../../develop/advanced-concepts/00-baseapp.md). ## Multistore -The Cosmos SDK provides a [`multistore`](../core/store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../core/store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../core/encoding.md) before being stored. +The Cosmos SDK provides a [`multistore`](../advanced-concepts/04-store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../advanced-concepts/04-store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../advanced-concepts/05-encoding.md) before being stored. -The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../core/store.md#multistore) +The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../advanced-concepts/04-store.md#multistore) ## Modules @@ -82,7 +78,7 @@ Here is a simplified view of how a transaction is processed by the application o v ``` -Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../core/ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. +Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../advanced-concepts/ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. Cosmos SDK modules are defined in the `x/` folder of the Cosmos SDK. Some core modules include: @@ -94,4 +90,4 @@ In addition to the already existing modules in `x/`, that anyone can use in thei ## Next {hide} -Learn more about the [anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {hide} +Learn more about the [anatomy of a Cosmos SDK application](../high-level-concepts/app-anatomy.md) {hide} diff --git a/versioned_docs/version-0.46/develop/intro/README.md b/versioned_docs/version-0.46/develop/intro/README.md deleted file mode 100644 index d20de3560..000000000 --- a/versioned_docs/version-0.46/develop/intro/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - -# Introduction - -This introduction gives a quick start on the Cosmos SDK. - -1. [Overview](./overview.md) -2. [Application-Specific Blockchains](./why-app-specific.md) -3. [Architecture of a Cosmos SDK Application](./sdk-app-architecture.md) -4. [Cosmos SDK Design Overview](./sdk-design.md) - -After reading the introduction material, head over to the [basics](../basics/README.md) to learn more. diff --git a/versioned_docs/version-0.46/develop/intro/_category_.json b/versioned_docs/version-0.46/develop/intro/_category_.json new file mode 100644 index 000000000..b218fe9be --- /dev/null +++ b/versioned_docs/version-0.46/develop/intro/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Introduction", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/CosmWasm/_category_.json b/versioned_docs/version-0.46/integrate/CosmWasm/_category_.json new file mode 100644 index 000000000..e4e9f1986 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/CosmWasm/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "CosmWasm", + "position": 4, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/_category_.json b/versioned_docs/version-0.46/integrate/_category_.json new file mode 100644 index 000000000..b860342f4 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Integrate", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/architecture/_category_.json b/versioned_docs/version-0.46/integrate/architecture/_category_.json new file mode 100644 index 000000000..f613ef834 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/architecture/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Architecture", + "position": 6, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/architecture/adr-003-dynamic-capability-store.md b/versioned_docs/version-0.46/integrate/architecture/adr-003-dynamic-capability-store.md index 4ec3f1a61..02f2a20b1 100644 --- a/versioned_docs/version-0.46/integrate/architecture/adr-003-dynamic-capability-store.md +++ b/versioned_docs/version-0.46/integrate/architecture/adr-003-dynamic-capability-store.md @@ -8,7 +8,7 @@ ## Context Full implementation of the [IBC specification](https://github.com/cosmos/ibs) requires the ability to create and authenticate object-capability keys at runtime (i.e., during transaction execution), -as described in [ICS 5](https://github.com/cosmos/ibc/tree/master/spec/core/ics-005-port-allocation#technical-specification). In the IBC specification, capability keys are created for each newly initialised +as described in [ICS 5](https://github.com/cosmos/ibc/tree/master/spec/01-tx-lifecycle.mdics-005-port-allocation#technical-specification). In the IBC specification, capability keys are created for each newly initialised port & channel, and are used to authenticate future usage of the port or channel. Since channels and potentially ports can be initialised during transaction execution, the state machine must be able to create object-capability keys at this time. diff --git a/versioned_docs/version-0.46/integrate/architecture/adr-017-historical-header-module.md b/versioned_docs/version-0.46/integrate/architecture/adr-017-historical-header-module.md index b97b46d4f..8cce973b0 100644 --- a/versioned_docs/version-0.46/integrate/architecture/adr-017-historical-header-module.md +++ b/versioned_docs/version-0.46/integrate/architecture/adr-017-historical-header-module.md @@ -58,4 +58,4 @@ Implementation of this ADR will require changes to the Cosmos SDK. It will not r ## References -* [ICS 2: "Consensus state introspection"](https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#consensus-state-introspection) +* [ICS 2: "Consensus state introspection"](https://github.com/cosmos/ibc/tree/master/spec/01-tx-lifecycle.mdics-002-client-semantics#consensus-state-introspection) diff --git a/versioned_docs/version-0.46/integrate/architecture/adr-033-protobuf-inter-module-comm.md b/versioned_docs/version-0.46/integrate/architecture/adr-033-protobuf-inter-module-comm.md index 09b650a61..1bf7f8b04 100644 --- a/versioned_docs/version-0.46/integrate/architecture/adr-033-protobuf-inter-module-comm.md +++ b/versioned_docs/version-0.46/integrate/architecture/adr-033-protobuf-inter-module-comm.md @@ -20,7 +20,7 @@ service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) a ## Context -In the current Cosmos SDK documentation on the [Object-Capability Model](../core/ocap.md), it is stated that: +In the current Cosmos SDK documentation on the [Object-Capability Model](../01-tx-lifecycle.mdocap.md), it is stated that: > We assume that a thriving ecosystem of Cosmos SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. @@ -397,4 +397,4 @@ replacing `Keeper` interfaces altogether. * [ADR 031](./adr-031-msg-service.md) * [ADR 028](./adr-028-public-key-addresses.md) * [ADR 030 draft](https://github.com/cosmos/cosmos-sdk/pull/7105) -* [Object-Capability Model](../docs/core/ocap.md) +* [Object-Capability Model](../docs/01-tx-lifecycle.mdocap.md) diff --git a/versioned_docs/version-0.46/integrate/architecture/adr-038-state-listening.md b/versioned_docs/version-0.46/integrate/architecture/adr-038-state-listening.md index 74f92d2f6..12d0bdb8b 100644 --- a/versioned_docs/version-0.46/integrate/architecture/adr-038-state-listening.md +++ b/versioned_docs/version-0.46/integrate/architecture/adr-038-state-listening.md @@ -19,7 +19,7 @@ This ADR defines a set of changes to enable listening to state changes of indivi ## Context -Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/02-messages-and-queries.md#queries) which proceed either through Tendermint and the ABCI, or through the gRPC server. In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. diff --git a/versioned_docs/version-0.46/integrate/architecture/adr-040-storage-and-smt-state-commitments.md b/versioned_docs/version-0.46/integrate/architecture/adr-040-storage-and-smt-state-commitments.md index f60e3adcf..5d7f6c89d 100644 --- a/versioned_docs/version-0.46/integrate/architecture/adr-040-storage-and-smt-state-commitments.md +++ b/versioned_docs/version-0.46/integrate/architecture/adr-040-storage-and-smt-state-commitments.md @@ -23,7 +23,7 @@ In the current design, IAVL is used for both data storage and as a Merkle Tree f * Each edge traversal requires a DB query. * Creating snapshots is [expensive](https://github.com/cosmos/cosmos-sdk/issues/7215#issuecomment-684804950). It takes about 30 seconds to export less than 100 MB of state (as of March 2020). * Updates in IAVL may trigger tree reorganization and possible O(log(n)) hashes re-computation, which can become a CPU bottleneck. -* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/node.md +* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/03-node.md ). Moreover, the IAVL project lacks support and a maintainer and we already see better and well-established alternatives. Instead of optimizing the IAVL, we are looking into other solutions for both storage and state commitments. @@ -177,7 +177,7 @@ The new `RootStore` and supporting types can be implemented in a `store/v2alpha1 #### Merkle Proofs and IBC -Currently, an IBC (v1.0) Merkle proof path consists of two elements (`["", ""]`), with each key corresponding to a separate proof. These are each verified according to individual [ICS-23 specs](https://github.com/cosmos/ibc-go/blob/f7051429e1cf833a6f65d51e6c3df1609290a549/modules/core/23-commitment/types/merkle.go#L17), and the result hash of each step is used as the committed value of the next step, until a root commitment hash is obtained. +Currently, an IBC (v1.0) Merkle proof path consists of two elements (`["", ""]`), with each key corresponding to a separate proof. These are each verified according to individual [ICS-23 specs](https://github.com/cosmos/ibc-go/blob/f7051429e1cf833a6f65d51e6c3df1609290a549/modules/01-tx-lifecycle.md23-commitment/types/merkle.go#L17), and the result hash of each step is used as the committed value of the next step, until a root commitment hash is obtained. The root hash of the proof for `""` is hashed with the `""` to validate against the App Hash. This is not compatible with the `RootStore`, which stores all records in a single Merkle tree structure, and won't produce separate proofs for the store- and record-key. Ideally, the store-key component of the proof could just be omitted, and updated to use a "no-op" spec, so only the record-key is used. However, because the IBC verification code hardcodes the `"ibc"` prefix and applies it to the SDK proof as a separate element of the proof path, this isn't possible without a breaking change. Breaking this behavior would severely impact the Cosmos ecosystem which already widely adopts the IBC module. Requesting an update of the IBC module across the chains is a time consuming effort and not easily feasible. diff --git a/versioned_docs/version-0.47/integrate/building-modules/01-intro.md b/versioned_docs/version-0.46/integrate/building-modules/00-intro.md similarity index 83% rename from versioned_docs/version-0.47/integrate/building-modules/01-intro.md rename to versioned_docs/version-0.46/integrate/building-modules/00-intro.md index bb45d5d13..590289b88 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/01-intro.md +++ b/versioned_docs/version-0.46/integrate/building-modules/00-intro.md @@ -1,29 +1,19 @@ ---- -sidebar_position: 1 ---- - # Introduction to Cosmos SDK Modules -:::note Synopsis -Modules define most of the logic of Cosmos SDK applications. Developers compose modules together using the Cosmos SDK to build their custom application-specific blockchains. This document outlines the basic concepts behind SDK modules and how to approach module management. -::: - -:::note - -### Pre-requisite Readings +Modules define most of the logic of Cosmos SDK applications. Developers compose modules together using the Cosmos SDK to build their custom application-specific blockchains. This document outlines the basic concepts behind SDK modules and how to approach module management. {synopsis} -* [Anatomy of a Cosmos SDK application](../basics/00-app-anatomy.md) -* [Lifecycle of a Cosmos SDK transaction](../basics/01-tx-lifecycle.md) +## Pre-requisite Readings -::: +* [Anatomy of a Cosmos SDK application](../high-level-concepts/app-anatomy.md) {prereq} +* [Lifecycle of a Cosmos SDK transaction](../high-level-concepts/01-tx-lifecycle.md) {prereq} ## Role of Modules in a Cosmos SDK Application -The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../core/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../core/04-store.md#multistore) to persist state, a [server](../core/03-node.md) to form a full-node and [interfaces](./09-module-interfaces.md) to handle queries. +The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../../develop/advanced-concepts/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../advanced-concepts/04-store.md#multistore) to persist state, a [server](../advanced-concepts/03-node.md) to form a full-node and [interfaces](./09-module-interfaces.md) to handle queries. On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source Cosmos SDK modules, making it increasingly easier to build complex blockchain applications. -Cosmos SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../core/04-store.md), as well as a subset of [message types](./02-messages-and-queries.md#messages). These messages are routed by one of the main components of Cosmos SDK core, [`BaseApp`](../core/00-baseapp.md), to a module Protobuf [`Msg` service](./03-msg-services.md) that defines them. +Cosmos SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../advanced-concepts/04-store.md), as well as a subset of [message types](./02-messages-and-queries.md#messages). These messages are routed by one of the main components of Cosmos SDK core, [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md), to a module Protobuf [`Msg` service](./03-msg-services.md) that defines them. ```text + @@ -65,7 +55,7 @@ Cosmos SDK modules can be seen as little state-machines within the state-machine | +--------------------------+ | - | Return result to the underlying consensus engine (e.g. CometBFT) + | Return result to the underlying consensus engine (e.g. Tendermint) | (0=Ok, 1=Err) v ``` @@ -77,7 +67,7 @@ As a result of this architecture, building a Cosmos SDK application usually revo While there are no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them: * **Composability**: Cosmos SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./06-keeper.md). -* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../core/10-ocap.md) of the Cosmos SDK. +* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../advanced-concepts/ocap.md) of the Cosmos SDK. * **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./06-keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. ## Main Components of Cosmos SDK Modules @@ -85,10 +75,14 @@ While there are no definitive guidelines for writing modules, here are some impo Modules are by convention defined in the `./x/` subfolder (e.g. the `bank` module will be defined in the `./x/bank` folder). They generally share the same core components: * A [`keeper`](./06-keeper.md), used to access the module's store(s) and update the state. -* A [`Msg` service](./02-messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../core/00-baseapp.md#message-routing) and trigger state-transitions. -* A [query service](./04-query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../core/00-baseapp.md#query-routing). +* A [`Msg` service](./02-messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#message-routing) and trigger state-transitions. +* A [query service](./04-query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#query-routing). * Interfaces, for end users to query the subset of the state defined by the module and create `message`s of the custom types defined in the module. In addition to these components, modules implement the `AppModule` interface in order to be managed by the [`module manager`](./01-module-manager.md). Please refer to the [structure document](./11-structure.md) to learn about the recommended structure of a module's directory. + +## Next {hide} + +Read more on the [`AppModule` interface and the `module manager`](./01-module-manager.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/module-manager.md b/versioned_docs/version-0.46/integrate/building-modules/01-module-manager.md similarity index 63% rename from versioned_docs/version-0.46/integrate/building-modules/module-manager.md rename to versioned_docs/version-0.46/integrate/building-modules/01-module-manager.md index edcab0388..96144e688 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/module-manager.md +++ b/versioned_docs/version-0.46/integrate/building-modules/01-module-manager.md @@ -1,10 +1,6 @@ - - # Module Manager -Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../core/baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#begingblocker-and-endblocker). {synopsis} +Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../../develop/advanced-concepts/00-baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../high-level-concepts/app-anatomy.md#begingblocker-and-endblocker). {synopsis} ## Pre-requisite Readings @@ -18,9 +14,9 @@ Application module interfaces exist to facilitate the composition of modules tog * [`AppModule`](#appmodule) for inter-dependent module functionalities (except genesis-related functionalities). * [`AppModuleGenesis`](#appmodulegenesis) for inter-dependent genesis-related module functionalities. -The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../basics/app-anatomy.md#core-application-file). +The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../high-level-concepts/app-anatomy.md#core-application-file). -The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](./keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. +The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](./06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. Lastly the interface for genesis functionality `AppModuleGenesis` is separated out from full module functionality `AppModule` so that modules which are only used for genesis can take advantage of the `Module` patterns without having to define many placeholder functions. @@ -36,11 +32,11 @@ Let us go through the methods: * `Name()`: Returns the name of the module as a `string`. * `RegisterLegacyAminoCodec(*codec.LegacyAmino)`: Registers the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`. * `RegisterInterfaces(codectypes.InterfaceRegistry)`: Registers a module's interface types and their concrete implementations as `proto.Message`. -* `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. -* `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./genesis.md#validategenesis) function defined by the module developer. +* `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./08-genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. +* `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./08-genesis.md#validategenesis) function defined by the module developer. * `RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)`: Registers gRPC routes for the module. -* `GetTxCmd()`: Returns the root [`Tx` command](./module-interfaces.md#tx) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](./messages-and-queries.md#queries) defined in the module. -* `GetQueryCmd()`: Return the root [`query` command](./module-interfaces.md#query) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. +* `GetTxCmd()`: Returns the root [`Tx` command](./09-module-interfaces.md#tx) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](./02-messages-and-queries.md#queries) defined in the module. +* `GetQueryCmd()`: Return the root [`query` command](./09-module-interfaces.md#query) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. All the `AppModuleBasic` of an application are managed by the [`BasicManager`](#basicmanager). @@ -67,10 +63,10 @@ The `AppModule` interface defines the inter-dependent methods that modules need Let us go through the methods of `AppModule`: -* `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](./invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](./invariants.md#registry) triggers appropriate logic (most often the chain will be halted). -* `Route()` (deprecated): Returns the route for [`message`s](./messages-and-queries.md#messages) to be routed to the module by [`BaseApp`](../core/baseapp.md#message-routing). -* `QuerierRoute()` (deprecated): Returns the name of the module's query route, for [`queries`](./messages-and-queries.md#queries) to be routes to the module by [`BaseApp`](../core/baseapp.md#query-routing). -* `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. +* `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](./07-invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](./07-invariants.md#registry) triggers appropriate logic (most often the chain will be halted). +* `Route()` (deprecated): Returns the route for [`message`s](./02-messages-and-queries.md#messages) to be routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#message-routing). +* `QuerierRoute()` (deprecated): Returns the name of the module's query route, for [`queries`](./02-messages-and-queries.md#queries) to be routes to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#query-routing). +* `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./04-query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. * `RegisterServices(Configurator)`: Allows a module to register services. * `BeginBlock(sdk.Context, abci.RequestBeginBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. Implement empty if no logic needs to be triggered at the beginning of each block for this module. * `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the end of each block for this module. @@ -79,7 +75,7 @@ Let us go through the methods of `AppModule`: Typically, the various application module interfaces are implemented in a file called `module.go`, located in the module's folder (e.g. `./x/module/module.go`). -Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./keeper.md) as a parameter. +Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./06-keeper.md) as a parameter. ```go // example @@ -109,14 +105,14 @@ The `BasicManager` is a structure that lists all the `AppModuleBasic` of an appl It implements the following methods: -* `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../basics/app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/main/app/app.go#L59-L74) to see an example). -* `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../core/encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../basics/app-anatomy.md#constructor). +* `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../high-level-concepts/app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/main/app/app.go#L59-L74) to see an example). +* `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../01-tx-lifecycle.md05-encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../high-level-concepts/app-anatomy.md#constructor). * `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModuleBasic`. -* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./genesis.md#defaultgenesis) function of each module. It is used to construct a default genesis file for the application. -* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./genesis.md#validategenesis) function of each module. +* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It is used to construct a default genesis file for the application. +* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of each module. * `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules. -* `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../core/cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/cli.md). -* `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../core/cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/cli.md). +* `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../01-tx-lifecycle.md06-cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../01-tx-lifecycle.md06-cli.md). +* `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../01-tx-lifecycle.md06-cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../01-tx-lifecycle.md06-cli.md). ### `Manager` @@ -126,21 +122,21 @@ The `Manager` is a structure that holds all the `AppModule` of an application, a The module manager is used throughout the application whenever an action on a collection of modules is required. It implements the following methods: -* `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -* `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). +* `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +* `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). To initialize modules successfully, module dependencies should be considered. For example, the `genutil` module must occur after `staking` module so that the pools are properly initialized with tokens from genesis accounts, the `genutils` module must also occur after `auth` so that it can access the params from auth, `capability` module should be initialized before all other modules so that it can initialize any capabilities. -* `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -* `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -* `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). +* `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +* `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). +* `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../high-level-concepts/app-anatomy.md#constructor-function). * `SetOrderMigrations(moduleNames ...string)`: Sets the order of migrations to be run. If not set then migrations will be run with an order defined in `DefaultMigrationsOrder`. -* `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./invariants.md) of each module. -* `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./messages-and-queries.md#messages) and [`querier`](./query-services.md#legacy-queriers) routes. +* `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./07-invariants.md) of each module. +* `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./02-messages-and-queries.md#messages) and [`querier`](./04-query-services.md#legacy-queriers) routes. * `RegisterServices(cfg Configurator)`: Registers all module services. -* `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. -* `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. -* `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../core/baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderBeginBlockers`. It creates a child [context](../core/context.md) with an event manager to aggregate [events](../core/events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. -* `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../core/baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderEndBlockers`. It creates a child [context](../core/context.md) with an event manager to aggregate [events](../core/events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). +* `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. +* `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. +* `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderBeginBlockers`. It creates a child [context](../01-tx-lifecycle.md02-context.md) with an event manager to aggregate [events](../01-tx-lifecycle.md07-events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. +* `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./beginblock-endblock.md) function of each module, in the order defined in `OrderEndBlockers`. It creates a child [context](../01-tx-lifecycle.md02-context.md) with an event manager to aggregate [events](../01-tx-lifecycle.md07-events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). Here's an example of a concrete integration within an application: @@ -148,4 +144,4 @@ Here's an example of a concrete integration within an application: ## Next {hide} -Learn more about [`message`s and `queries`](./messages-and-queries.md) {hide} +Learn more about [`message`s and `queries`](./02-messages-and-queries.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/messages-and-queries.md b/versioned_docs/version-0.46/integrate/building-modules/02-messages-and-queries.md similarity index 72% rename from versioned_docs/version-0.46/integrate/building-modules/messages-and-queries.md rename to versioned_docs/version-0.46/integrate/building-modules/02-messages-and-queries.md index 6e075bf42..7b1124359 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/messages-and-queries.md +++ b/versioned_docs/version-0.46/integrate/building-modules/02-messages-and-queries.md @@ -1,7 +1,3 @@ - - # Messages and Queries `Msg`s and `Queries` are the two primary objects handled by modules. Most of the core components defined in a module, like `Msg` services, `keeper`s and `Query` services, exist to process `message`s and `queries`. {synopsis} @@ -12,13 +8,13 @@ order: 3 ## Messages -`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../core/transactions.md), which may contain one or more of them. +`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../advanced-concepts/01-transactions.md), which may contain one or more of them. -When a transaction is relayed from the underlying consensus engine to the Cosmos SDK application, it is first decoded by [`BaseApp`](../core/baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](./msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../basics/tx-lifecycle.md). +When a transaction is relayed from the underlying consensus engine to the Cosmos SDK application, it is first decoded by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](./03-msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../high-level-concepts/01-tx-lifecycle.md). ### `Msg` Services -Defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../core/encoding.md#faq)). It must have an RPC service method defined for each message in the module. +Defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../advanced-concepts/05-encoding.md#faq)). It must have an RPC service method defined for each message in the module. See an example of a `Msg` service definition from `x/bank` module: @@ -34,10 +30,10 @@ Each `Msg` service method must have exactly one argument, which must implement t The Cosmos SDK uses Protobuf definitions to generate client and server code: -* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](./msg-services.md) documentation. +* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](./03-msg-services.md) documentation. * Structures are generated for all RPC request and response types. -A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./module-manager.md#appmodule). +A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). In order for clients (CLI and grpc-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](module-manager.md#appmodulebasic) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument. @@ -47,15 +43,15 @@ The following way of defining messages is deprecated and using [`Msg` services]( Amino `LegacyMsg`s can be defined as protobuf messages. The messages definition usually includes a list of parameters needed to process the message that will be provided by end-users when they want to create a new transaction containing said message. -A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](./module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: +A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](./09-module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/types/tx_msg.go#L10-L22 It extends `proto.Message` and contains the following methods: * `Route() string`: Name of the route for this message. Typically all `message`s in a module have the same route, which is most often the module's name. -* `Type() string`: Type of the message, used primarily in [events](../core/events.md). This should return a message-specific `string`, typically the denomination of the message itself. -* [`ValidateBasic() error`](../basics/tx-lifecycle.md#ValidateBasic). +* `Type() string`: Type of the message, used primarily in [events](../advanced-concepts/07-events.md). This should return a message-specific `string`, typically the denomination of the message itself. +* [`ValidateBasic() error`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic). * `GetSignBytes() []byte`: Return the canonical byte representation of the message. Used to generate a signature. * `GetSigners() []AccAddress`: Return the list of signers. The Cosmos SDK will make sure that each `message` contained in a transaction is signed by all the signers listed in the list returned by this method. @@ -67,7 +63,7 @@ See an example implementation of a `message` from the `gov` module: ## Queries -A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `QueryRouter` so that it can be processed by the module's query service (./query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../basics/query-lifecycle.md). +A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `QueryRouter` so that it can be processed by the module's query service (./04-query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../high-level-concepts/query-lifecycle.md). ### gRPC Queries @@ -79,7 +75,7 @@ Here's an example of such a `Query` service definition: As `proto.Message`s, generated `Response` types implement by default `String()` method of [`fmt.Stringer`](https://pkg.go.dev/fmt#Stringer). -A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](./module-manager.md#appmodule). +A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). ### Legacy Queries @@ -91,15 +87,15 @@ queryCategory/queryRoute/queryType/arg1/arg2/... where: -* `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../core/baseapp.md#query). -* `queryRoute` is used by `BaseApp`'s [`queryRouter`](../core/baseapp.md#query-routing) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. -* `queryType` is used by the module's [`querier`](./query-services.md#legacy-queriers) to map the `query` to the appropriate `querier function` within the module. +* `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). +* `queryRoute` is used by `BaseApp`'s [`queryRouter`](../../develop/advanced-concepts/00-baseapp.md#query-routing) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. +* `queryType` is used by the module's [`querier`](./04-query-services.md#legacy-queriers) to map the `query` to the appropriate `querier function` within the module. * `args` are the actual arguments needed to process the `query`. They are filled out by the end-user. Note that for bigger queries, you might prefer passing arguments in the `Data` field of the request `req` instead of the `path`. -The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](./module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: +The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](./09-module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: -* A [`querier`](./query-services.md#legacy-queriers), to process the `query` once it has been [routed to the module](../core/baseapp.md#query-routing). -* [Query commands](./module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. +* A [`querier`](./04-query-services.md#legacy-queriers), to process the `query` once it has been [routed to the module](../../develop/advanced-concepts/00-baseapp.md#query-routing). +* [Query commands](./09-module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. * `query` return types. Typically defined in a file `types/querier.go`, they specify the result type of each of the module's `queries`. These custom types must implement the `String()` method of [`fmt.Stringer`](https://pkg.go.dev/fmt#Stringer). ### Store Queries @@ -112,4 +108,4 @@ See following examples: ## Next {hide} -Learn about [`Msg` services](./msg-services.md) {hide} +Learn about [`Msg` services](./03-msg-services.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/msg-services.md b/versioned_docs/version-0.46/integrate/building-modules/03-msg-services.md similarity index 72% rename from versioned_docs/version-0.46/integrate/building-modules/msg-services.md rename to versioned_docs/version-0.46/integrate/building-modules/03-msg-services.md index 164160ef5..6db59fa4a 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/msg-services.md +++ b/versioned_docs/version-0.46/integrate/building-modules/03-msg-services.md @@ -1,15 +1,11 @@ - - # `Msg` Services -A Protobuf `Msg` service processes [messages](./messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../core/baseapp.md#delivertx). {synopsis} +A Protobuf `Msg` service processes [messages](./02-messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx). {synopsis} ## Pre-requisite Readings -* [Module Manager](./module-manager.md) {prereq} -* [Messages and Queries](./messages-and-queries.md) {prereq} +* [Module Manager](./01-module-manager.md) {prereq} +* [Messages and Queries](./02-messages-and-queries.md) {prereq} ## Implementation of a module `Msg` service @@ -33,7 +29,7 @@ When possible, the existing module's [`Keeper`](keeper.md) should implement `Msg ### Validation -Before a `msgServer` method is executed, the message's [`ValidateBasic()`](../basics/tx-lifecycle.md#ValidateBasic) method has already been called. Since `msg.ValidateBasic()` performs only the most basic checks, this stage must perform all other validation (both *stateful* and *stateless*) to make sure the `message` is valid. Checks performed in the `msgServer` method can be more expensive and the signer is charged gas for these operations. +Before a `msgServer` method is executed, the message's [`ValidateBasic()`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) method has already been called. Since `msg.ValidateBasic()` performs only the most basic checks, this stage must perform all other validation (both *stateful* and *stateless*) to make sure the `message` is valid. Checks performed in the `msgServer` method can be more expensive and the signer is charged gas for these operations. For example, a `msgServer` method for a `transfer` message might check that the sending account has enough funds to actually perform the transfer. It is recommended to implement all validation checks in a separate function that passes state values as arguments. This implementation simplifies testing. As expected, expensive validation functions charge additional gas. Example: @@ -50,11 +46,11 @@ ValidateMsgA(msg MsgA, now Time, gm GasMeter) error { ### State Transition -After the validation is successful, the `msgServer` method uses the [`keeper`](./keeper.md) functions to access the state and perform a state transition. +After the validation is successful, the `msgServer` method uses the [`keeper`](./06-keeper.md) functions to access the state and perform a state transition. ### Events -Before returning, `msgServer` methods generally emit one or more [events](../core/events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: +Before returning, `msgServer` methods generally emit one or more [events](../advanced-concepts/07-events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: ```go ctx.EventManager().EmitTypedEvent( @@ -73,7 +69,7 @@ ctx.EventManager().EmitEvent( ) ``` -These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../core/events.md) to learn more about events. +These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../advanced-concepts/07-events.md) to learn more about events. The invoked `msgServer` method returns a `proto.Message` response and an `error`. These return values are then wrapped into an `*sdk.Result` or an `error` using `sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error)`: @@ -89,7 +85,7 @@ This diagram shows a typical structure of a Protobuf `Msg` service, and how the ## Telemetry -New [telemetry metrics](../core/telemetry.md) can be created from `msgServer` methods when handling messages. +New [telemetry metrics](../advanced-concepts/11-telemetry.md) can be created from `msgServer` methods when handling messages. This is an example from the `x/auth/vesting` module: @@ -97,4 +93,4 @@ This is an example from the `x/auth/vesting` module: ## Next {hide} -Learn about [query services](./query-services.md) {hide} +Learn about [query services](./04-query-services.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/query-services.md b/versioned_docs/version-0.46/integrate/building-modules/04-query-services.md similarity index 64% rename from versioned_docs/version-0.46/integrate/building-modules/query-services.md rename to versioned_docs/version-0.46/integrate/building-modules/04-query-services.md index 4618480a6..c8b794a28 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/query-services.md +++ b/versioned_docs/version-0.46/integrate/building-modules/04-query-services.md @@ -1,15 +1,11 @@ - - # Query Services -A Protobuf Query service processes [`queries`](./messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../core/baseapp.md#query). {synopsis} +A Protobuf Query service processes [`queries`](./02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). {synopsis} ## Pre-requisite Readings -* [Module Manager](./module-manager.md) {prereq} -* [Messages and Queries](./messages-and-queries.md) {prereq} +* [Module Manager](./01-module-manager.md) {prereq} +* [Messages and Queries](./02-messages-and-queries.md) {prereq} ## `Querier` type @@ -19,10 +15,10 @@ The `querier` type defined in the Cosmos SDK will be deprecated in favor of [gRP Let us break it down: -* The [`Context`](../core/context.md) contains all the necessary information needed to process the `query`, as well as a branch of the latest state. It is primarily used by the [`keeper`](./keeper.md) to access the state. -* The `path` is an array of `string`s that contains the type of the query, and that can also contain `query` arguments. See [`queries`](./messages-and-queries.md#queries) for more information. +* The [`Context`](../advanced-concepts/02-context.md) contains all the necessary information needed to process the `query`, as well as a branch of the latest state. It is primarily used by the [`keeper`](./06-keeper.md) to access the state. +* The `path` is an array of `string`s that contains the type of the query, and that can also contain `query` arguments. See [`queries`](./02-messages-and-queries.md#queries) for more information. * The `req` itself is primarily used to retrieve arguments if they are too large to fit in the `path`. This is done using the `Data` field of `req`. -* The result in `[]byte` returned to `BaseApp`, marshalled using the application's [`codec`](../core/encoding.md). +* The result in `[]byte` returned to `BaseApp`, marshalled using the application's [`codec`](../advanced-concepts/05-encoding.md). ## Implementation of a module query service @@ -47,7 +43,7 @@ Here's an example implementation for the bank module: ### Legacy Queriers -Module legacy `querier`s are typically implemented in a `./keeper/querier.go` file inside the module's folder. The [module manager](./module-manager.md) is used to add the module's `querier`s to the [application's `queryRouter`](../core/baseapp.md#query-routing) via the `NewQuerier()` method. Typically, the manager's `NewQuerier()` method simply calls a `NewQuerier()` method defined in `keeper/querier.go`, which looks like the following: +Module legacy `querier`s are typically implemented in a `./keeper/querier.go` file inside the module's folder. The [module manager](./01-module-manager.md) is used to add the module's `querier`s to the [application's `queryRouter`](../../develop/advanced-concepts/00-baseapp.md#query-routing) via the `NewQuerier()` method. Typically, the manager's `NewQuerier()` method simply calls a `NewQuerier()` method defined in `keeper/querier.go`, which looks like the following: ```go func NewQuerier(keeper Keeper) sdk.Querier { @@ -66,9 +62,9 @@ func NewQuerier(keeper Keeper) sdk.Querier { } ``` -This simple switch returns a `querier` function specific to the type of the received `query`. At this point of the [query lifecycle](../basics/query-lifecycle.md), the first element of the `path` (`path[0]`) contains the type of the query. The following elements are either empty or contain arguments needed to process the query. +This simple switch returns a `querier` function specific to the type of the received `query`. At this point of the [query lifecycle](../high-level-concepts/query-lifecycle.md), the first element of the `path` (`path[0]`) contains the type of the query. The following elements are either empty or contain arguments needed to process the query. -The `querier` functions themselves are pretty straightforward. They generally fetch a value or values from the state using the [`keeper`](./keeper.md). Then, they marshall the value(s) using the [`codec`](../core/encoding.md) and return the `[]byte` obtained as result. +The `querier` functions themselves are pretty straightforward. They generally fetch a value or values from the state using the [`keeper`](./06-keeper.md). Then, they marshall the value(s) using the [`codec`](../01-tx-lifecycle.md05-encoding.md) and return the `[]byte` obtained as result. For a deeper look at `querier`s, see this [example implementation of a `querier` function](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/gov/keeper/querier.go) from the bank module. diff --git a/versioned_docs/version-0.46/integrate/building-modules/beginblock-endblock.md b/versioned_docs/version-0.46/integrate/building-modules/05-beginblock-endblock.md similarity index 62% rename from versioned_docs/version-0.46/integrate/building-modules/beginblock-endblock.md rename to versioned_docs/version-0.46/integrate/building-modules/05-beginblock-endblock.md index e324018fc..541a3dfb1 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/beginblock-endblock.md +++ b/versioned_docs/version-0.46/integrate/building-modules/05-beginblock-endblock.md @@ -1,30 +1,26 @@ - - # BeginBlocker and EndBlocker -`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../core/baseapp.md#beginblock) and [`EndBlock`](../core/baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. {synopsis} +`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and [`EndBlock`](../../develop/advanced-concepts/00-baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. {synopsis} ## Pre-requisite Readings -* [Module Manager](./module-manager.md) {prereq} +* [Module Manager](./01-module-manager.md) {prereq} ## BeginBlocker and EndBlocker `BeginBlocker` and `EndBlocker` are a way for module developers to add automatic execution of logic to their module. This is a powerful tool that should be used carefully, as complex automatic functions can slow down or even halt the chain. -When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`AppModule` interface](./module-manager.md#appmodule). The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. +When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`AppModule` interface](./01-module-manager.md#appmodule). The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. -The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./msg-services.md): +The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./03-msg-services.md): -* They generally use the [`keeper`](./keeper.md) and [`ctx`](../core/context.md) to retrieve information about the latest state. +* They generally use the [`keeper`](./06-keeper.md) and [`ctx`](../advanced-concepts/02-context.md) to retrieve information about the latest state. * If needed, they use the `keeper` and `ctx` to trigger state-transitions. -* If needed, they can emit [`events`](../core/events.md) via the `ctx`'s `EventManager`. +* If needed, they can emit [`events`](../advanced-concepts/07-events.md) via the `ctx`'s `EventManager`. A specificity of the `EndBlocker` is that it can return validator updates to the underlying consensus engine in the form of an [`[]abci.ValidatorUpdates`](https://docs.tendermint.com/master/spec/abci/abci.html#validatorupdate). This is the preferred way to implement custom validator changes. -It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). +It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./01-module-manager.md#manager). See an example implementation of `BeginBlocker` from the `distribution` module: @@ -36,4 +32,4 @@ and an example implementation of `EndBlocker` from the `staking` module: ## Next {hide} -Learn about [`keeper`s](./keeper.md) {hide} +Learn about [`keeper`s](./06-keeper.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/keeper.md b/versioned_docs/version-0.46/integrate/building-modules/06-keeper.md similarity index 70% rename from versioned_docs/version-0.46/integrate/building-modules/keeper.md rename to versioned_docs/version-0.46/integrate/building-modules/06-keeper.md index 78712a91b..68892af3e 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/keeper.md +++ b/versioned_docs/version-0.46/integrate/building-modules/06-keeper.md @@ -1,7 +1,3 @@ - - # Keepers `Keeper`s refer to a Cosmos SDK abstraction whose role is to manage access to the subset of the state defined by various modules. `Keeper`s are module-specific, i.e. the subset of state defined by a module can only be accessed by a `keeper` defined in said module. If a module needs to access the subset of state defined by another module, a reference to the second module's internal `keeper` needs to be passed to the first one. This is done in `app.go` during the instantiation of module keepers. {synopsis} @@ -14,9 +10,9 @@ order: 7 The Cosmos SDK is a framework that makes it easy for developers to build complex decentralized applications from scratch, mainly by composing modules together. As the ecosystem of open-source modules for the Cosmos SDK expands, it will become increasingly likely that some of these modules contain vulnerabilities, as a result of the negligence or malice of their developer. -The Cosmos SDK adopts an [object-capabilities-based approach](../core/ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be considered quite literally to be the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../core/store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). +The Cosmos SDK adopts an [object-capabilities-based approach](../advanced-concepts/ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be considered quite literally to be the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../advanced-concepts/04-store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). -The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../basics/app-anatomy.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. +The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. ## Type Definition @@ -39,14 +35,14 @@ For example, here is the type definition of the `keeper` from the `staking` modu Let us go through the different parameters: * An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself. -* `storeKey`s grant access to the store(s) of the [multistore](../core/store.md) managed by the module. They should always remain unexposed to external modules. -* `cdc` is the [codec](../core/encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. +* `storeKey`s grant access to the store(s) of the [multistore](../advanced-concepts/04-store.md) managed by the module. They should always remain unexposed to external modules. +* `cdc` is the [codec](../advanced-concepts/05-encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. -Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../basics/app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. +Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../high-level-concepts/app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. ## Implementing Methods -`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed via the `ValidateBasic()` method of the [`message`](./messages-and-queries.md#messages) and the [`Msg` server](./msg-services.md) when `keeper`s' methods are called. +`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed via the `ValidateBasic()` method of the [`message`](./02-messages-and-queries.md#messages) and the [`Msg` server](./03-msg-services.md) when `keeper`s' methods are called. Typically, a *getter* method will have the following signature @@ -74,7 +70,7 @@ and the method will go through the following steps: For more, see an example of `keeper`'s [methods implementation from the `staking` module](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/staking/keeper/keeper.go). -The [module `KVStore`](../core/store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. +The [module `KVStore`](../advanced-concepts/04-store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. This is an example from the `auth` module to iterate accounts: @@ -82,4 +78,4 @@ This is an example from the `auth` module to iterate accounts: ## Next {hide} -Learn about [invariants](./invariants.md) {hide} +Learn about [invariants](./07-invariants.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/invariants.md b/versioned_docs/version-0.46/integrate/building-modules/07-invariants.md similarity index 81% rename from versioned_docs/version-0.46/integrate/building-modules/invariants.md rename to versioned_docs/version-0.46/integrate/building-modules/07-invariants.md index 0cbb0adac..359039dee 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/invariants.md +++ b/versioned_docs/version-0.46/integrate/building-modules/07-invariants.md @@ -1,14 +1,10 @@ - - # Invariants An invariant is a property of the application that should always be true. In the context of the Cosmos SDK, an `Invariant` is a function that checks for a particular invariant. These functions are useful to detect bugs early on and act upon them to limit their potential consequences (e.g. by halting the chain). They are also useful in the development process of the application to detect bugs via simulations. {synopsis} ## Pre-requisite Readings -* [Keepers](./keeper.md) {prereq} +* [Keepers](./06-keeper.md) {prereq} ## Implementing `Invariant`s @@ -49,7 +45,7 @@ func AllInvariants(k Keeper) sdk.Invariant { } ``` -Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](./module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): +Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](./01-module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/staking/keeper/invariants.go#L12-L21 @@ -67,9 +63,9 @@ Typically, this interface is implemented in the `keeper` of a specific module. T +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/crisis/keeper/keeper.go#L49-L53 - The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../basics/app-anatomy.md#constructor-function). + The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function). -`Invariant`s can be checked manually via [`message`s](./messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: +`Invariant`s can be checked manually via [`message`s](./02-messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/crisis/abci.go#L12-L21 @@ -77,4 +73,4 @@ In both cases, if one of the `Invariant`s returns false, the `InvariantRegistry` ## Next {hide} -Learn about [genesis functionalities](./genesis.md) {hide} +Learn about [genesis functionalities](./08-genesis.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/genesis.md b/versioned_docs/version-0.46/integrate/building-modules/08-genesis.md similarity index 60% rename from versioned_docs/version-0.46/integrate/building-modules/genesis.md rename to versioned_docs/version-0.46/integrate/building-modules/08-genesis.md index 9e9c57738..2406e10b9 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/genesis.md +++ b/versioned_docs/version-0.46/integrate/building-modules/08-genesis.md @@ -1,19 +1,15 @@ - - # Module Genesis Modules generally handle a subset of the state and, as such, they need to define the related subset of the genesis file as well as methods to initialize, verify and export it. {synopsis} ## Pre-requisite Readings -* [Module Manager](./module-manager.md) {prereq} -* [Keepers](./keeper.md) {prereq} +* [Module Manager](./01-module-manager.md) {prereq} +* [Keepers](./06-keeper.md) {prereq} ## Type Definition -The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../core/encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. +The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../advanced-concepts/05-encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. See an example of `GenesisState` protobuf message definition from the `auth` module: @@ -35,13 +31,13 @@ The `ValidateGenesis(data GenesisState)` method is called to verify that the pro ## Other Genesis Methods -Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](./module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). +Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](./01-module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). ### `InitGenesis` -The `InitGenesis` method is executed during [`InitChain`](../core/baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](./keeper.md) setter function on each parameter within the `GenesisState`. +The `InitGenesis` method is executed during [`InitChain`](../../develop/advanced-concepts/00-baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](./06-keeper.md) setter function on each parameter within the `GenesisState`. -The [module manager](./module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../basics/app-anatomy.md#constructor-function). +The [module manager](./01-module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../high-level-concepts/app-anatomy.md#constructor-function). See an example of `InitGenesis` from the `auth` module: diff --git a/versioned_docs/version-0.46/integrate/building-modules/module-interfaces.md b/versioned_docs/version-0.46/integrate/building-modules/09-module-interfaces.md similarity index 84% rename from versioned_docs/version-0.46/integrate/building-modules/module-interfaces.md rename to versioned_docs/version-0.46/integrate/building-modules/09-module-interfaces.md index 91dca7a53..d189941e3 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/module-interfaces.md +++ b/versioned_docs/version-0.46/integrate/building-modules/09-module-interfaces.md @@ -1,7 +1,3 @@ - - # Module Interfaces This document details how to build CLI and REST interfaces for a module. Examples from various Cosmos SDK modules are included. {synopsis} @@ -12,11 +8,11 @@ This document details how to build CLI and REST interfaces for a module. Example ## CLI -One of the main interfaces for an application is the [command-line interface](../core/cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](./messages-and-queries.md#messages) wrapped in transactions and [**queries**](./messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. +One of the main interfaces for an application is the [command-line interface](../advanced-concepts/06-cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](./02-messages-and-queries.md#messages) wrapped in transactions and [**queries**](./02-messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. ### Transaction Commands -In order to create messages that trigger state changes, end-users must create [transactions](../core/transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. +In order to create messages that trigger state changes, end-users must create [transactions](../advanced-concepts/01-transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. Transaction commands typically have their own `tx.go` file that lives within the module's `./client/cli` folder. The commands are specified in getter functions and the name of the function should include the name of the command. @@ -35,7 +31,7 @@ In general, the getter function does the following: * **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new transaction. * The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientTxContext(cmd)`. The `clientCtx` contains information relevant to transaction handling, including information about the user. In this example, the `clientCtx` is used to retrieve the address of the sender by calling `clientCtx.GetFromAddress()`. * If applicable, the command's arguments are parsed. In this example, the arguments `[to_address]` and `[amount]` are both parsed. - * A [message](./messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call [`msg.ValidateBasic()`](../basics/tx-lifecycle.md#ValidateBasic) and other validation methods before broadcasting the message. + * A [message](./02-messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call [`msg.ValidateBasic()`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) and other validation methods before broadcasting the message. * Depending on what the user wants, the transaction is either generated offline or signed and broadcasted to the preconfigured node using `tx.GenerateOrBroadcastTxCLI(clientCtx, flags, msg)`. * **Adds transaction flags:** All transaction commands must add a set of transaction [flags](#flags). The transaction flags are used to collect additional information from the user (e.g. the amount of fees the user is willing to pay). The transaction flags are added to the constructed command using `AddTxFlagsToCmd(cmd)`. * **Returns the command:** Finally, the transaction command is returned. @@ -50,7 +46,7 @@ Each module must also implement the `GetTxCmd()` method for `AppModuleBasic` tha ### Query Commands -[Queries](./messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: +[Queries](./02-messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/x/auth/client/cli/query.go#L83-L125 @@ -65,7 +61,7 @@ In general, the getter function does the following: * **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new query. * The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientQueryContext(cmd)`. The `clientCtx` contains information relevant to query handling. * If applicable, the command's arguments are parsed. In this example, the argument `[address]` is parsed. - * A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./messages-and-queries.md#grpc-queries). + * A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./02-messages-and-queries.md#grpc-queries). * The `clientCtx.PrintProto` method is used to format the `proto.Message` object so that the results can be printed back to the user. * **Adds query flags:** All query commands must add a set of query [flags](#flags). The query flags are added to the constructed command using `AddQueryFlagsToCmd(cmd)`. * **Returns the command:** Finally, the query command is returned. @@ -80,7 +76,7 @@ Each module must also implement the `GetQueryCmd()` method for `AppModuleBasic` ### Flags -[Flags](../core/cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../basics/gas-fees.md) and gas prices for their transactions. +[Flags](../01-tx-lifecycle.md06-cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../high-level-concepts/gas-fees.md) and gas prices for their transactions. Flags that are specific to a module are typically created in a `flags.go` file in the module's `./client/cli` folder. When creating a flag, developers set the value type, the name of the flag, the default value, and a description about the flag. Developers also have the option to mark flags as _required_ so that an error is thrown if the user does not include a value for the flag. @@ -136,4 +132,4 @@ The Cosmos SDK provides a command for generating [Swagger](https://swagger.io/) ## Next {hide} -Read about the recommended [module structure](./structure.md) {hide} +Read about the recommended [module structure](./11-structure.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/structure.md b/versioned_docs/version-0.46/integrate/building-modules/11-structure.md similarity index 98% rename from versioned_docs/version-0.46/integrate/building-modules/structure.md rename to versioned_docs/version-0.46/integrate/building-modules/11-structure.md index 70885833f..043bcfaa6 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/structure.md +++ b/versioned_docs/version-0.46/integrate/building-modules/11-structure.md @@ -1,7 +1,3 @@ - - # Recommended Folder Structure This document outlines the recommended structure of Cosmos SDK modules. These ideas are meant to be applied as suggestions. Application developers are encouraged to improve upon and contribute to module structure and development design. {synopsis} @@ -96,4 +92,4 @@ x/{module_name} ## Next {hide} -Learn about [Errors](./errors.md) {hide} +Learn about [Errors](./12-errors.md) {hide} diff --git a/versioned_docs/version-0.46/integrate/building-modules/errors.md b/versioned_docs/version-0.46/integrate/building-modules/12-errors.md similarity index 99% rename from versioned_docs/version-0.46/integrate/building-modules/errors.md rename to versioned_docs/version-0.46/integrate/building-modules/12-errors.md index 9e7b970fc..62d7a572c 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/errors.md +++ b/versioned_docs/version-0.46/integrate/building-modules/12-errors.md @@ -1,7 +1,3 @@ - - # Errors This document outlines the recommended usage and APIs for error handling in Cosmos SDK modules. {synopsis} diff --git a/versioned_docs/version-0.46/integrate/building-modules/upgrade.md b/versioned_docs/version-0.46/integrate/building-modules/13-upgrade.md similarity index 90% rename from versioned_docs/version-0.46/integrate/building-modules/upgrade.md rename to versioned_docs/version-0.46/integrate/building-modules/13-upgrade.md index 863066ca7..4f2ef3e0e 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/upgrade.md +++ b/versioned_docs/version-0.46/integrate/building-modules/13-upgrade.md @@ -1,14 +1,10 @@ - - # Upgrading Modules -[In-Place Store Migrations](../core/upgrade.md) allow your modules to upgrade to new versions that include breaking changes. This document outlines how to build modules to take advantage of this functionality. {synopsis} +[In-Place Store Migrations](../advanced-concepts/13-upgrade.md) allow your modules to upgrade to new versions that include breaking changes. This document outlines how to build modules to take advantage of this functionality. {synopsis} ## Prerequisite Readings -* [In-Place Store Migration](../core/upgrade.md) {prereq} +* [In-Place Store Migration](../advanced-concepts/13-upgrade.md) {prereq} ## Consensus Version diff --git a/versioned_docs/version-0.46/integrate/building-modules/simulator.md b/versioned_docs/version-0.46/integrate/building-modules/14-simulator.md similarity index 98% rename from versioned_docs/version-0.46/integrate/building-modules/simulator.md rename to versioned_docs/version-0.46/integrate/building-modules/14-simulator.md index 4c2196dad..0ed80a148 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/simulator.md +++ b/versioned_docs/version-0.46/integrate/building-modules/14-simulator.md @@ -57,7 +57,7 @@ Operations are one of the crucial parts of the Cosmos SDK simulation. They are t (`Msg`) that are simulated with random field values. The sender of the operation is also assigned randomly. -Operations on the simulation are simulated using the full [transaction cycle](../core/transactions.md) of a +Operations on the simulation are simulated using the full [transaction cycle](../advanced-concepts/01-transactions.md) of a `ABCI` application that exposes the `BaseApp`. Shown below is how weights are set: diff --git a/versioned_docs/version-0.46/integrate/building-modules/README.md b/versioned_docs/version-0.46/integrate/building-modules/README.md deleted file mode 100644 index 8dd53c945..000000000 --- a/versioned_docs/version-0.46/integrate/building-modules/README.md +++ /dev/null @@ -1,23 +0,0 @@ - - -# Building Modules - -This repository contains documentation on concepts developers need to know in order to build modules for Cosmos SDK applications. - -1. [Introduction to Cosmos SDK Modules](./intro.md) -2. [`AppModule` Interface and Module Manager](./module-manager.md) -3. [Messages and Queries](./messages-and-queries.md) -4. [`Msg` services - Processing Messages](./msg-services.md) -5. [Query Services - Processing Queries](./query-services.md) -6. [BeginBlocker and EndBlocker](./beginblock-endblock.md) -7. [`Keeper`s](./keeper.md) -8. [Invariants](./invariants.md) -9. [Genesis](./genesis.md) -10. [Module Interfaces](./module-interfaces.md) -11. [Standard Module Structure](./structure.md) -12. [Errors](./errors.md) -13. [In-Place Store Migrations](./upgrade.md) diff --git a/versioned_docs/version-0.46/integrate/building-modules/_category_.json b/versioned_docs/version-0.46/integrate/building-modules/_category_.json new file mode 100644 index 000000000..17bc3fc57 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/building-modules/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Building Modules", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/ibc/_category_.json b/versioned_docs/version-0.46/integrate/ibc/_category_.json new file mode 100644 index 000000000..5241a91e8 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/ibc/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IBC", + "position": 3, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/migrations/pre-upgrade.md b/versioned_docs/version-0.46/integrate/migrations/00-pre-upgrade.md similarity index 100% rename from versioned_docs/version-0.46/integrate/migrations/pre-upgrade.md rename to versioned_docs/version-0.46/integrate/migrations/00-pre-upgrade.md diff --git a/versioned_docs/version-0.46/integrate/migrations/README.md b/versioned_docs/version-0.46/integrate/migrations/README.md deleted file mode 100644 index b5e08ec46..000000000 --- a/versioned_docs/version-0.46/integrate/migrations/README.md +++ /dev/null @@ -1,13 +0,0 @@ - - -# Migrations - -This document contains all the migration guides to update your app and modules to the current Cosmos SDK. - -1. Chain Upgrade Guide to v0.46: - * See [UPGRADING.md (TODO)](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md) for breaking changes and deprecations upgrade instructions. - * See [Release Notes](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/RELEASE_NOTES.md) and [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/CHANGELOG.md) for the exhaustive list of API and State Machine breaking changes. diff --git a/versioned_docs/version-0.46/integrate/migrations/_category_.json b/versioned_docs/version-0.46/integrate/migrations/_category_.json new file mode 100644 index 000000000..e28fa8a0c --- /dev/null +++ b/versioned_docs/version-0.46/integrate/migrations/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Migrations", + "position": 5, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/_category_.json b/versioned_docs/version-0.46/integrate/modules/_category_.json new file mode 100644 index 000000000..136eee1a4 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Modules", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/auth/01_concepts.md b/versioned_docs/version-0.46/integrate/modules/auth/01_concepts.md index e028ebe8e..a0475f058 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/01_concepts.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/01_concepts.md @@ -1,7 +1,3 @@ - - # Concepts **Note:** The auth module is different from the [authz module](../modules/authz/). diff --git a/versioned_docs/version-0.46/integrate/modules/auth/02_state.md b/versioned_docs/version-0.46/integrate/modules/auth/02_state.md index 560e93421..8853e9ba9 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/02_state.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/02_state.md @@ -1,7 +1,3 @@ - - # State ## Accounts diff --git a/versioned_docs/version-0.46/integrate/modules/auth/03_antehandlers.md b/versioned_docs/version-0.46/integrate/modules/auth/03_antehandlers.md index 3227d8dff..7e10af878 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/03_antehandlers.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/03_antehandlers.md @@ -1,7 +1,3 @@ - - # AnteHandlers The `x/auth` module presently has no transaction handlers of its own, but does expose the special `AnteHandler`, used for performing basic validity checks on a transaction, such that it could be thrown out of the mempool. diff --git a/versioned_docs/version-0.46/integrate/modules/auth/04_keepers.md b/versioned_docs/version-0.46/integrate/modules/auth/04_keepers.md index 268ced5c3..130d3a6ea 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/04_keepers.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/04_keepers.md @@ -1,7 +1,3 @@ - - # Keepers The auth module only exposes one keeper, the account keeper, which can be used to read and write accounts. diff --git a/versioned_docs/version-0.46/integrate/modules/auth/05_vesting.md b/versioned_docs/version-0.46/integrate/modules/auth/05_vesting.md index 2108c658c..38c294577 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/05_vesting.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/05_vesting.md @@ -1,7 +1,3 @@ - - # Vesting * [Vesting](#vesting) diff --git a/versioned_docs/version-0.46/integrate/modules/auth/06_params.md b/versioned_docs/version-0.46/integrate/modules/auth/06_params.md index 414e1888f..1250aaa31 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/06_params.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/06_params.md @@ -1,7 +1,3 @@ - - # Parameters The auth module contains the following parameters: diff --git a/versioned_docs/version-0.46/integrate/modules/auth/07_client.md b/versioned_docs/version-0.46/integrate/modules/auth/07_client.md index bcfdc6f6f..0e0129be5 100644 --- a/versioned_docs/version-0.46/integrate/modules/auth/07_client.md +++ b/versioned_docs/version-0.46/integrate/modules/auth/07_client.md @@ -1,7 +1,3 @@ - - # Client # Auth diff --git a/versioned_docs/version-0.46/integrate/modules/auth/_category_.json b/versioned_docs/version-0.46/integrate/modules/auth/_category_.json new file mode 100644 index 000000000..f8162812b --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/auth/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Auth", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/authz/01_concepts.md b/versioned_docs/version-0.46/integrate/modules/authz/01_concepts.md index ffe810b59..9259c3b17 100644 --- a/versioned_docs/version-0.46/integrate/modules/authz/01_concepts.md +++ b/versioned_docs/version-0.46/integrate/modules/authz/01_concepts.md @@ -1,7 +1,3 @@ - - # Concepts ## Authorization and Grant diff --git a/versioned_docs/version-0.46/integrate/modules/authz/02_state.md b/versioned_docs/version-0.46/integrate/modules/authz/02_state.md index ac5df1022..24552b626 100644 --- a/versioned_docs/version-0.46/integrate/modules/authz/02_state.md +++ b/versioned_docs/version-0.46/integrate/modules/authz/02_state.md @@ -1,7 +1,3 @@ - - # State ## Grant diff --git a/versioned_docs/version-0.46/integrate/modules/authz/03_messages.md b/versioned_docs/version-0.46/integrate/modules/authz/03_messages.md index 2dfca9c7c..e9203168f 100644 --- a/versioned_docs/version-0.46/integrate/modules/authz/03_messages.md +++ b/versioned_docs/version-0.46/integrate/modules/authz/03_messages.md @@ -1,7 +1,3 @@ - - # Messages In this section we describe the processing of messages for the authz module. diff --git a/versioned_docs/version-0.46/integrate/modules/authz/04_events.md b/versioned_docs/version-0.46/integrate/modules/authz/04_events.md index 1729b49a7..b5fd09752 100644 --- a/versioned_docs/version-0.46/integrate/modules/authz/04_events.md +++ b/versioned_docs/version-0.46/integrate/modules/authz/04_events.md @@ -1,7 +1,3 @@ - - # Events The authz module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main/cosmos.authz.v1beta1#cosmos.authz.v1beta1.EventGrant). diff --git a/versioned_docs/version-0.46/integrate/modules/authz/05_client.md b/versioned_docs/version-0.46/integrate/modules/authz/05_client.md index f2ca6cc94..5b27e58e8 100644 --- a/versioned_docs/version-0.46/integrate/modules/authz/05_client.md +++ b/versioned_docs/version-0.46/integrate/modules/authz/05_client.md @@ -1,7 +1,3 @@ - - # Client ## CLI diff --git a/versioned_docs/version-0.46/integrate/modules/authz/_category_.json b/versioned_docs/version-0.46/integrate/modules/authz/_category_.json new file mode 100644 index 000000000..d77e44faf --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/authz/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Authz", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/bank/_category_.json b/versioned_docs/version-0.46/integrate/modules/bank/_category_.json new file mode 100644 index 000000000..26ef5343c --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/bank/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Bank", + "position": 2, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/capability/01_concepts.md b/versioned_docs/version-0.46/integrate/modules/capability/01_concepts.md index 93ecb6354..28a19e06e 100644 --- a/versioned_docs/version-0.46/integrate/modules/capability/01_concepts.md +++ b/versioned_docs/version-0.46/integrate/modules/capability/01_concepts.md @@ -1,7 +1,3 @@ - - # Concepts ## Capabilities diff --git a/versioned_docs/version-0.46/integrate/modules/capability/02_state.md b/versioned_docs/version-0.46/integrate/modules/capability/02_state.md index 3ab713bdb..4d77a034e 100644 --- a/versioned_docs/version-0.46/integrate/modules/capability/02_state.md +++ b/versioned_docs/version-0.46/integrate/modules/capability/02_state.md @@ -1,7 +1,3 @@ - - # State ## In persisted KV store diff --git a/versioned_docs/version-0.46/integrate/modules/capability/_category_.json b/versioned_docs/version-0.46/integrate/modules/capability/_category_.json new file mode 100644 index 000000000..76516372b --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/capability/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Capability", + "position": 3, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/01_state.md b/versioned_docs/version-0.46/integrate/modules/crisis/01_state.md index 50003e63d..dea835dae 100644 --- a/versioned_docs/version-0.46/integrate/modules/crisis/01_state.md +++ b/versioned_docs/version-0.46/integrate/modules/crisis/01_state.md @@ -1,7 +1,3 @@ - - # State ## ConstantFee diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/02_messages.md b/versioned_docs/version-0.46/integrate/modules/crisis/02_messages.md index ca3b650f5..e712f5eae 100644 --- a/versioned_docs/version-0.46/integrate/modules/crisis/02_messages.md +++ b/versioned_docs/version-0.46/integrate/modules/crisis/02_messages.md @@ -1,7 +1,3 @@ - - # Messages In this section we describe the processing of the crisis messages and the diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/03_events.md b/versioned_docs/version-0.46/integrate/modules/crisis/03_events.md index 5aef2078e..f645e823b 100644 --- a/versioned_docs/version-0.46/integrate/modules/crisis/03_events.md +++ b/versioned_docs/version-0.46/integrate/modules/crisis/03_events.md @@ -1,7 +1,3 @@ - - # Events The crisis module emits the following events: diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/04_params.md b/versioned_docs/version-0.46/integrate/modules/crisis/04_params.md index 0d046adaa..19ccc3648 100644 --- a/versioned_docs/version-0.46/integrate/modules/crisis/04_params.md +++ b/versioned_docs/version-0.46/integrate/modules/crisis/04_params.md @@ -1,7 +1,3 @@ - - # Parameters The crisis module contains the following parameters: diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/05_client.md b/versioned_docs/version-0.46/integrate/modules/crisis/05_client.md index 5f95955a6..09ad513e8 100644 --- a/versioned_docs/version-0.46/integrate/modules/crisis/05_client.md +++ b/versioned_docs/version-0.46/integrate/modules/crisis/05_client.md @@ -1,7 +1,3 @@ - - # Client ## CLI diff --git a/versioned_docs/version-0.46/integrate/modules/crisis/_category_.json b/versioned_docs/version-0.46/integrate/modules/crisis/_category_.json new file mode 100644 index 000000000..1e851ca4b --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/crisis/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Crisis", + "position": 4, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/distribution/_category_.json b/versioned_docs/version-0.46/integrate/modules/distribution/_category_.json new file mode 100644 index 000000000..e83c5672d --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/distribution/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Distribution", + "position": 5, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/evidence/_category_.json b/versioned_docs/version-0.46/integrate/modules/evidence/_category_.json new file mode 100644 index 000000000..49492c8d5 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/evidence/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Evidence", + "position": 6, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/feegrant/_category_.json b/versioned_docs/version-0.46/integrate/modules/feegrant/_category_.json new file mode 100644 index 000000000..4616ef3b7 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/feegrant/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Feegrant", + "position": 7, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/gov/_category_.json b/versioned_docs/version-0.46/integrate/modules/gov/_category_.json new file mode 100644 index 000000000..03024ef30 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/gov/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Gov", + "position": 8, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/mint/_category_.json b/versioned_docs/version-0.46/integrate/modules/mint/_category_.json new file mode 100644 index 000000000..a2d53fc97 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/mint/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Mint", + "position": 9, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/params/_category_.json b/versioned_docs/version-0.46/integrate/modules/params/_category_.json new file mode 100644 index 000000000..e79e238db --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/params/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Params", + "position": 10, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/slashing/_category_.json b/versioned_docs/version-0.46/integrate/modules/slashing/_category_.json new file mode 100644 index 000000000..97d1fa939 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/slashing/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Slashing", + "position": 11, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/staking/_category_.json b/versioned_docs/version-0.46/integrate/modules/staking/_category_.json new file mode 100644 index 000000000..9ee26e8d5 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/staking/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Staking", + "position": 12, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/upgrade/_category_.json b/versioned_docs/version-0.46/integrate/modules/upgrade/_category_.json new file mode 100644 index 000000000..afd841085 --- /dev/null +++ b/versioned_docs/version-0.46/integrate/modules/upgrade/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Upgrade", + "position": 13, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/user/_category_.json b/versioned_docs/version-0.46/user/_category_.json new file mode 100644 index 000000000..9b291ba6f --- /dev/null +++ b/versioned_docs/version-0.46/user/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "User Guides", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.46/user/run-node/keyring.md b/versioned_docs/version-0.46/user/run-node/00-keyring.md similarity index 96% rename from versioned_docs/version-0.46/user/run-node/keyring.md rename to versioned_docs/version-0.46/user/run-node/00-keyring.md index 8506ef4c0..38e9b1a02 100644 --- a/versioned_docs/version-0.46/user/run-node/keyring.md +++ b/versioned_docs/version-0.46/user/run-node/00-keyring.md @@ -1,10 +1,6 @@ - - # Setting up the keyring -This document describes how to configure and use the keyring and its various backends for an [**application**](../basics/app-anatomy.md). {synopsis} +This document describes how to configure and use the keyring and its various backends for an [**application**](../high-level-concepts/app-anatomy.md). {synopsis} The keyring holds the private/public keypairs used to interact with a node. For instance, a validator key needs to be set up before running the blockchain node, so that blocks can be correctly signed. The private key can be stored in different locations, called "backends", such as a file or the operating system's own key storage. @@ -129,7 +125,7 @@ MY_VALIDATOR_ADDRESS=$(simd keys show my_validator -a --keyring-backend test) This command generates a new 24-word mnemonic phrase, persists it to the relevant backend, and outputs information about the keypair. If this keypair will be used to hold value-bearing tokens, be sure to write down the mnemonic phrase somewhere safe! -By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [middlewares](../core/baseapp.md#middleware)) supports natively these two public key algorithms. +By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [middlewares](../../develop/advanced-concepts/00-baseapp.md#middleware)) supports natively these two public key algorithms. ## Next {hide} diff --git a/versioned_docs/version-0.46/user/run-node/run-node.md b/versioned_docs/version-0.46/user/run-node/01-run-node.md similarity index 95% rename from versioned_docs/version-0.46/user/run-node/run-node.md rename to versioned_docs/version-0.46/user/run-node/01-run-node.md index 19f2aa6bc..e396eb609 100644 --- a/versioned_docs/version-0.46/user/run-node/run-node.md +++ b/versioned_docs/version-0.46/user/run-node/01-run-node.md @@ -1,14 +1,10 @@ - - # Running a Node Now that the application is ready and the keyring populated, it's time to see how to run the blockchain node. In this section, the application we are running is called [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp), and its corresponding CLI binary `simd`. {synopsis} ## Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](../basics/app-anatomy.md) {prereq} +* [Anatomy of a Cosmos SDK Application](../high-level-concepts/app-anatomy.md) {prereq} * [Setting up the keyring](./keyring.md) {prereq} ## Initialize the Chain @@ -127,7 +123,7 @@ The naive way would be to run the same commands again in separate terminal windo ## State Sync -State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.34/core/state-sync). +State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.34/01-tx-lifecycle.mdstate-sync). State sync works thanks to snapshots. Read how the SDK handles snapshots [here](https://github.com/cosmos/cosmos-sdk/blob/825245d/store/snapshots/README.md). @@ -135,7 +131,7 @@ State sync works thanks to snapshots. Read how the SDK handles snapshots [here]( Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. -1. As mentioned in https://docs.cometbft.com/v0.34/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). +1. As mentioned in https://docs.cometbft.com/v0.34/01-tx-lifecycle.mdstate-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). 2. Run ` ` to restore a local snapshot (note: first load it from a file with the *load* command). 3. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` tendermint bootstrap-state` diff --git a/versioned_docs/version-0.46/user/run-node/interact-node.md b/versioned_docs/version-0.46/user/run-node/02-interact-node.md similarity index 93% rename from versioned_docs/version-0.46/user/run-node/interact-node.md rename to versioned_docs/version-0.46/user/run-node/02-interact-node.md index 0daf04e51..c37bfa96a 100644 --- a/versioned_docs/version-0.46/user/run-node/interact-node.md +++ b/versioned_docs/version-0.46/user/run-node/02-interact-node.md @@ -1,14 +1,10 @@ - - # Interacting with the Node There are multiple ways to interact with a node: using the CLI, using gRPC or using the REST endpoints. {synopsis} ## Pre-requisite Readings -* [gRPC, REST and Tendermint Endpoints](../core/grpc_rest.md) {prereq} +* [gRPC, REST and Tendermint Endpoints](../01-tx-lifecycle.md08-grpc_rest.md) {prereq} * [Running a Node](./run-node.md) {prereq} ## Using the CLI @@ -50,7 +46,7 @@ You should see two delegations, the first one made from the `gentx`, and the sec ## Using gRPC -The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/grpc_rest.md). +The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../01-tx-lifecycle.md08-grpc_rest.md). Since the code generation library largely depends on your own tech stack, we will only present three alternatives: @@ -214,7 +210,7 @@ CosmJS documentation can be found at [https://cosmos.github.io/cosmjs](https://c ## Using the REST Endpoints -As described in the [gRPC guide](../core/grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. +As described in the [gRPC guide](../01-tx-lifecycle.md08-grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. As a concrete example, the `curl` command to make balances request is: diff --git a/versioned_docs/version-0.46/user/run-node/txs.md b/versioned_docs/version-0.46/user/run-node/03-txs.md similarity index 99% rename from versioned_docs/version-0.46/user/run-node/txs.md rename to versioned_docs/version-0.46/user/run-node/03-txs.md index 9674d32f4..35951533b 100644 --- a/versioned_docs/version-0.46/user/run-node/txs.md +++ b/versioned_docs/version-0.46/user/run-node/03-txs.md @@ -1,7 +1,3 @@ - - # Generating, Signing and Broadcasting Transactions This document describes how to generate an (unsigned) transaction, signing it (with one or multiple keys), and broadcasting it to the network. {synopsis} @@ -265,7 +261,7 @@ func sendTx() error { ### Broadcasting a Transaction -The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the Tendermint RPC is also posible. An overview of the differences between these methods is exposed [here](../core/grpc_rest.md). For this tutorial, we will only describe the gRPC method. +The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the Tendermint RPC is also posible. An overview of the differences between these methods is exposed [here](../01-tx-lifecycle.md08-grpc_rest.md). For this tutorial, we will only describe the gRPC method. ```go import ( diff --git a/versioned_docs/version-0.46/user/run-node/rosetta.md b/versioned_docs/version-0.46/user/run-node/04-rosetta.md similarity index 99% rename from versioned_docs/version-0.46/user/run-node/rosetta.md rename to versioned_docs/version-0.46/user/run-node/04-rosetta.md index e3d94492f..06adaf5b4 100644 --- a/versioned_docs/version-0.46/user/run-node/rosetta.md +++ b/versioned_docs/version-0.46/user/run-node/04-rosetta.md @@ -1,7 +1,3 @@ - - # Rosetta The `rosetta` package implements Coinbase's [Rosetta API](https://www.rosetta-api.org). This document provides instructions on how to use the Rosetta API integration. For information about the motivation and design choices, refer to [ADR 035](../architecture/adr-035-rosetta-api-support.md). diff --git a/versioned_docs/version-0.46/user/run-node/run-testnet.md b/versioned_docs/version-0.46/user/run-node/05-run-testnet.md similarity index 99% rename from versioned_docs/version-0.46/user/run-node/run-testnet.md rename to versioned_docs/version-0.46/user/run-node/05-run-testnet.md index 55ad21d67..ce59a2492 100644 --- a/versioned_docs/version-0.46/user/run-node/run-testnet.md +++ b/versioned_docs/version-0.46/user/run-node/05-run-testnet.md @@ -1,7 +1,3 @@ - - # Running a Testnet The `simd testnet` subcommand makes it easy to initialize and start a simulated test network for testing purposes. {synopsis} diff --git a/versioned_docs/version-0.46/user/run-node/README.md b/versioned_docs/version-0.46/user/run-node/README.md deleted file mode 100644 index ec6eca8bd..000000000 --- a/versioned_docs/version-0.46/user/run-node/README.md +++ /dev/null @@ -1,17 +0,0 @@ - - -# Running a Node, API and CLI - -This script contains documentation on how to run a node and interact with it. - -1. [Setting up the keyring](./keyring.md) -2. [Running a Node](./run-node.md) -3. [Interacting with a Node](./interact-node.md) -4. [Generating, Signing and Broadcasting Transactions](./txs.md) -5. [Cosmos Upgrade Manager](./cosmovisor.md) -6. [Rosetta API](./rosetta.md) -7. [Running a Testnet](./run-testnet.md) diff --git a/versioned_docs/version-0.46/user/run-node/_category_.json b/versioned_docs/version-0.46/user/run-node/_category_.json new file mode 100644 index 000000000..9b291ba6f --- /dev/null +++ b/versioned_docs/version-0.46/user/run-node/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "User Guides", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/develop/_category_.json b/versioned_docs/version-0.47/develop/_category_.json new file mode 100644 index 000000000..f40637f4d --- /dev/null +++ b/versioned_docs/version-0.47/develop/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Develop", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/00-baseapp.md b/versioned_docs/version-0.47/develop/advanced-concepts/00-baseapp.md index e18267116..85b08bdde 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/00-baseapp.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/00-baseapp.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 1 ---- - # BaseApp :::note Synopsis @@ -12,8 +8,8 @@ This document describes `BaseApp`, the abstraction that implements the core func ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/00-app-anatomy.md) -* [Lifecycle of a Cosmos SDK transaction](../basics/01-tx-lifecycle.md) +* [Anatomy of a Cosmos SDK application](../high-level-concepts/00-overview-app.md) +* [Lifecycle of a Cosmos SDK transaction](../high-level-concepts/01-tx-lifecycle.md) ::: @@ -21,7 +17,7 @@ This document describes `BaseApp`, the abstraction that implements the core func `BaseApp` is a base type that implements the core of a Cosmos SDK application, namely: -* The [Application Blockchain Interface](#main-abci-messages), for the state-machine to communicate with the underlying consensus engine (e.g. CometBFT). +* The [Application Blockchain Interface](#main-abci-10-messages), for the state-machine to communicate with the underlying consensus engine (e.g. CometBFT). * [Service Routers](#service-routers), to route messages and queries to the appropriate module. * Different [states](#state-updates), as the state-machine can have different volatile states updated based on the ABCI message received. @@ -62,7 +58,7 @@ Let us go through the most important components. First, the important parameters that are initialized during the bootstrapping of the application: -* [`CommitMultiStore`](./04-store.md#commitmultistore): This is the main store of the application, +* [`CommitMultiStore`](04-store.md#commitmultistore): This is the main store of the application, which holds the canonical state that is committed at the [end of each block](#commit). This store is **not** cached, meaning it is not used to update the application's volatile (un-committed) states. The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application @@ -80,8 +76,8 @@ First, the important parameters that are initialized during the bootstrapping of * [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment, and other pre-message execution checks when a transaction is received. It's executed during [`CheckTx/RecheckTx`](#checktx) and [`DeliverTx`](#delivertx). -* [`InitChainer`](../basics/00-app-anatomy.md#initchainer), - [`BeginBlocker` and `EndBlocker`](../basics/00-app-anatomy.md#beginblocker-and-endblocker): These are +* [`InitChainer`](../high-level-concepts/00-overview-app.md#initchainer), + [`BeginBlocker` and `EndBlocker`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblocker): These are the functions executed when the application receives the `InitChain`, `BeginBlock` and `EndBlock` ABCI messages from the underlying CometBFT engine. @@ -97,7 +93,7 @@ Finally, a few more important parameters: * `voteInfos`: This parameter carries the list of validators whose precommit is missing, either because they did not vote or because the proposer did not include their vote. This information is - carried by the [Context](#context) and can be used by the application for various things like + carried by the and can be used by the application for various things like punishing absent validators. * `minGasPrices`: This parameter defines the minimum gas prices accepted by the node. This is a **local** parameter, meaning each full-node can set a different `minGasPrices`. It is used in the @@ -107,7 +103,7 @@ Finally, a few more important parameters: `minGasPrices` (e.g. if `minGasPrices == 1uatom,1photon`, the `gas-price` of the transaction must be greater than `1uatom` OR `1photon`). * `appVersion`: Version of the application. It is set in the - [application's constructor function](../basics/00-app-anatomy.md#constructor-function). + [application's constructor function](../high-level-concepts/00-overview-app.md#constructor-function). ## Constructor @@ -138,7 +134,7 @@ Internally, there is only a single `CommitMultiStore` which we refer to as the m From this root state, we derive four volatile states by using a mechanism called _store branching_ (performed by `CacheWrap` function). The types can be illustrated as follows: -![Types](./baseapp_state.png) +![Types](baseapp_state.png) ### InitChain State Updates @@ -147,7 +143,7 @@ and `deliverState` are set by branching the root `CommitMultiStore`. Any subsequ on branched versions of the `CommitMultiStore`. To avoid unnecessary roundtrip to the main state, all reads to the branched store are cached. -![InitChain](./baseapp_state-initchain.png) +![InitChain](baseapp_state-initchain.png) ### CheckTx State Updates @@ -158,7 +154,7 @@ the already branched `checkState`. This has the side effect that if the `AnteHandler` fails, the state transitions won't be reflected in the `checkState` -- i.e. `checkState` is only updated on success. -![CheckTx](./baseapp_state-checktx.png) +![CheckTx](baseapp_state-checktx.png) ### PrepareProposal State Updates @@ -171,7 +167,7 @@ during the execution of the proposal. The described behavior is that of the default handler, applications have the flexibility to define their own [custom mempool handlers](https://docs.cosmos.network/main/building-apps/app-mempool#custom-mempool-handlers). -![ProcessProposal](./baseapp_state-prepareproposal.png) +![ProcessProposal](baseapp_state-prepareproposal.png) ### ProcessProposal State Updates @@ -182,7 +178,7 @@ from the header and the main state, including the minimum gas prices, which are Again we want to highlight that the described behavior is that of the default handler and applications have the flexibility to define their own [custom mempool handlers](https://docs.cosmos.network/main/building-apps/app-mempool#custom-mempool-handlers). -![ProcessProposal](./baseapp_state-processproposal.png) +![ProcessProposal](baseapp_state-processproposal.png) ### BeginBlock State Updates @@ -190,7 +186,7 @@ During `BeginBlock`, the `deliverState` is set for use in subsequent `DeliverTx` `deliverState` is based off of the last committed state from the root store and is branched. Note, the `deliverState` is set to `nil` on [`Commit`](#commit). -![BeginBlock](./baseapp_state-begin_block.png) +![BeginBlock](baseapp_state-begin_block.png) ### DeliverTx State Updates @@ -200,7 +196,7 @@ occur on a doubly branched state -- `deliverState`. Successful message execution writes being committed to `deliverState`. Note, if message execution fails, state transitions from the AnteHandler are persisted. -![DeliverTx](./baseapp_state-deliver_tx.png) +![DeliverTx](baseapp_state-deliver_tx.png) ### Commit State Updates @@ -209,7 +205,7 @@ the root `CommitMultiStore` which in turn is committed to disk and results in a root hash. These state transitions are now considered final. Finally, the `checkState` is set to the newly committed state and `deliverState` is set to `nil` to be reset on `BeginBlock`. -![Commit](./baseapp_state-commit.png) +![Commit](baseapp_state-commit.png) ## ParamStore @@ -225,17 +221,17 @@ When messages and queries are received by the application, they must be routed t ### `Msg` Service Router -[`sdk.Msg`s](../building-modules/02-messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying CometBFT engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. +[`sdk.Msg`s](../../integrate/building-modules/02-messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying CometBFT engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `BaseApp` holds a `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation. The [default `msgServiceRouter` included in `BaseApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/msg_service_router.go) is stateless. However, some applications may want to make use of more stateful routing mechanisms such as allowing governance to disable certain routes or point them to new modules for upgrade purposes. For this reason, the `sdk.Context` is also passed into each [route handler inside `msgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/msg_service_router.go#L31-L32). For a stateless router that doesn't want to make use of this, you can just ignore the `ctx`. -The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/01-module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/00-app-anatomy.md#constructor-function). +The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../../integrate/building-modules/01-module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#constructor-function). ### gRPC Query Router -Similar to `sdk.Msg`s, [`queries`](../building-modules/02-messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/04-query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the CometBFT RPC endpoint. +Similar to `sdk.Msg`s, [`queries`](../../integrate/building-modules/02-messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../../integrate/building-modules/04-query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the CometBFT RPC endpoint. -Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/01-module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/00-app-anatomy.md#app-constructor). +Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../../integrate/building-modules/01-module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../high-level-concepts/00-overview-app.md#app-constructor). ## Main ABCI 1.0 Messages @@ -265,7 +261,7 @@ Here is how the `PrepareProposal` function can be implemented: 1. Extract the `sdk.Msg`s from the transaction. 2. Perform _stateful_ checks by calling `Validate()` on each of the `sdk.Msg`'s. This is done after _stateless_ checks as _stateful_ checks are more computationally expensive. If `Validate()` fails, `PrepareProposal` returns before running further checks, which saves resources. 3. Perform any additional checks that are specific to the application, such as checking account balances, or ensuring that certain conditions are met before a transaction is proposed.hey are processed by the consensus engine, if necessary. -5. Return the updated transactions to be processed by the consensus engine +4. Return the updated transactions to be processed by the consensus engine Note that, unlike `CheckTx()`, `PrepareProposal` process `sdk.Msg`s, so it can directly update the state. However, unlike `DeliverTx()`, it does not commit the state updates. It's important to exercise caution when using `PrepareProposal` as incorrect coding could affect the overall liveness of the network. @@ -316,27 +312,28 @@ Unconfirmed transactions are relayed to peers only if they pass `CheckTx`. `CheckTx()` can perform both _stateful_ and _stateless_ checks, but developers should strive to make the checks **lightweight** because gas fees are not charged for the resources (CPU, data load...) used during the `CheckTx`. -In the Cosmos SDK, after [decoding transactions](./05-encoding.md), `CheckTx()` is implemented +In the Cosmos SDK, after [decoding transactions](06-encoding.md), `CheckTx()` is implemented to do the following checks: 1. Extract the `sdk.Msg`s from the transaction. -2. Perform _stateless_ checks by calling `ValidateBasic()` on each of the `sdk.Msg`s. This is done +2. **Optionally** perform _stateless_ checks by calling `ValidateBasic()` on each of the `sdk.Msg`s. This is done first, as _stateless_ checks are less computationally expensive than _stateful_ checks. If `ValidateBasic()` fail, `CheckTx` returns before running _stateful_ checks, which saves resources. -3. Perform non-module related _stateful_ checks on the [account](../basics/03-accounts.md). This step is mainly about checking + This check is still performed for messages that have not yet migrated to the new message validation mechanism defined in [RFC 001](https://docs.cosmos.network/main/rfc/rfc-001-tx-validation) and still have a `ValidateBasic()` method. +3. Perform non-module related _stateful_ checks on the [account](../high-level-concepts/03-accounts.md). This step is mainly about checking that the `sdk.Msg` signatures are valid, that enough fees are provided and that the sending account - has enough funds to pay for said fees. Note that no precise [`gas`](../basics/04-gas-fees.md) counting occurs here, - as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../basics/04-gas-fees.md#antehandler) will check that the `gas` provided + has enough funds to pay for said fees. Note that no precise [`gas`](../high-level-concepts/04-gas-fees.md) counting occurs here, + as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../high-level-concepts/04-gas-fees.md#antehandler) will check that the `gas` provided with the transaction is superior to a minimum reference gas amount based on the raw transaction size, in order to avoid spam with transactions that provide 0 gas. `CheckTx` does **not** process `sdk.Msg`s - they only need to be processed when the canonical state need to be updated, which happens during `DeliverTx`. -Steps 2. and 3. are performed by the [`AnteHandler`](../basics/04-gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs) +Steps 2. and 3. are performed by the [`AnteHandler`](../high-level-concepts/04-gas-fees.md#antehandler) in the [`RunTx()`](#runtx) function, which `CheckTx()` calls with the `runTxModeCheck` mode. During each step of `CheckTx()`, a special [volatile state](#state-updates) called `checkState` is updated. This state is used to keep track of the temporary changes triggered by the `CheckTx()` calls of each transaction without modifying -the [main canonical state](#main-state). For example, when a transaction goes through `CheckTx()`, the +the [main canonical state](#state-updates). For example, when a transaction goes through `CheckTx()`, the transaction's fees are deducted from the sender's account in `checkState`. If a second transaction is received from the same account before the first is processed, and the account has consumed all its funds in `checkState` during the first transaction, the second transaction will fail `CheckTx`() and @@ -358,7 +355,7 @@ The response contains: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/ante/basic.go#L96 ``` -* `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./08-events.md) for more. +* `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](08-events.md) for more. * `Codespace (string)`: Namespace for the Code. #### RecheckTx @@ -374,12 +371,12 @@ This allows certain checks like signature verification can be skipped during `Ch When the underlying consensus engine receives a block proposal, each transaction in the block needs to be processed by the application. To that end, the underlying consensus engine sends a `DeliverTx` message to the application for each transaction in a sequential order. -Before the first transaction of a given block is processed, a [volatile state](#state-updates) called `deliverState` is initialized during [`BeginBlock`](#beginblock). This state is updated each time a transaction is processed via `DeliverTx`, and committed to the [main state](#main-state) when the block is [committed](#commit), after what it is set to `nil`. +Before the first transaction of a given block is processed, a [volatile state](#state-updates) called `deliverState` is initialized during [`BeginBlock`](#beginblock). This state is updated each time a transaction is processed via `DeliverTx`, and committed to the [main state](#state-updates) when the block is [committed](#commit), after what it is set to `nil`. `DeliverTx` performs the **exact same steps as `CheckTx`**, with a little caveat at step 3 and the addition of a fifth step: 1. The `AnteHandler` does **not** check that the transaction's `gas-prices` is sufficient. That is because the `min-gas-prices` value `gas-prices` is checked against is local to the node, and therefore what is enough for one full-node might not be for another. This means that the proposer can potentially include transactions for free, although they are not incentivised to do so, as they earn a bonus on the total fee of the block they propose. -2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. +2. For each `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: @@ -397,7 +394,7 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0 * `Info (string):` Additional information. May be non-deterministic. * `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction. * `GasUsed (int64)`: Amount of gas consumed by transaction. During `DeliverTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction, and by adding gas each time a read/write to the store occurs. -* `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./08-events.md) for more. +* `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](08-events.md) for more. * `Codespace (string)`: Namespace for the Code. ## RunTx, AnteHandler, RunMsgs, PostHandler @@ -406,9 +403,9 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0 `RunTx` is called from `CheckTx`/`DeliverTx` to handle the transaction, with `runTxModeCheck` or `runTxModeDeliver` as parameter to differentiate between the two modes of execution. Note that when `RunTx` receives a transaction, it has already been decoded. -The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../basics/04-gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. +The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a branch of the main store, with cache functionality (for query requests), instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../high-level-concepts/04-gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any. -After that, `RunTx()` calls `ValidateBasic()` on each `sdk.Msg`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `sdk.Msg` fails to pass `ValidateBasic()`, `RunTx()` returns with an error. +After that, `RunTx()` calls `ValidateBasic()`, when available and for backward compatibility, on each `sdk.Msg`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `sdk.Msg` fails to pass `ValidateBasic()`, `RunTx()` returns with an error. Then, the [`anteHandler`](#antehandler) of the application is run (if it exists). In preparation of this step, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are branched using the `cacheTxContext()` function. @@ -416,7 +413,7 @@ Then, the [`anteHandler`](#antehandler) of the application is run (if it exists) https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/baseapp.go#L663-L672 ``` -This allows `RunTx` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](./10-ocap.md) of the Cosmos SDK. +This allows `RunTx` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](10-ocap.md) of the Cosmos SDK. Finally, the [`RunMsgs()`](#runmsgs) function is called to process the `sdk.Msg`s in the `Tx`. In preparation of this step, just like with the `anteHandler`, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are branched using the `cacheTxContext()` function. @@ -430,19 +427,19 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/handler.go#L6-L8 The `AnteHandler` is theoretically optional, but still a very important component of public blockchain networks. It serves 3 primary purposes: -* Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and [`sequence`](./01-transactions.md#transaction-generation) checking. +* Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and [`sequence`](01-transactions.md#transaction-generation) checking. * Perform preliminary _stateful_ validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees. * Play a role in the incentivisation of stakeholders via the collection of transaction fees. -`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../basics/00-app-anatomy.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/ante/ante.go). +`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../high-level-concepts/00-overview-app.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/ante/ante.go). -Click [here](../basics/04-gas-fees.md#antehandler) for more on the `anteHandler`. +Click [here](../high-level-concepts/04-gas-fees.md#antehandler) for more on the `anteHandler`. ### RunMsgs `RunMsgs` is called from `RunTx` with `runTxModeCheck` as parameter to check the existence of a route for each message the transaction, and with `runTxModeDeliver` to actually process the `sdk.Msg`s. -First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/03-msg-services.md) RPC is executed, before `RunMsgs` returns. +First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../../integrate/building-modules/03-msg-services.md) RPC is executed, before `RunMsgs` returns. ### PostHandler @@ -465,9 +462,9 @@ The [`InitChain` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x * [Consensus Parameters](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_app_requirements.md#consensus-parameters) via `setConsensusParams`. * [`checkState` and `deliverState`](#state-updates) via `setState`. -* The [block gas meter](../basics/04-gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. +* The [block gas meter](../high-level-concepts/04-gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions. -Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../basics/00-app-anatomy.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/08-genesis.md#initgenesis) function of each of the application's modules. +Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls the [`initChainer()`](../high-level-concepts/00-overview-app.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../../integrate/building-modules/08-genesis.md#initgenesis) function of each of the application's modules. ### BeginBlock @@ -479,15 +476,15 @@ The [`BeginBlock` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37. https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/baseapp.go#L406-L433 ``` - This function also resets the [main gas meter](../basics/04-gas-fees.md#main-gas-meter). + This function also resets the [main gas meter](../high-level-concepts/04-gas-fees.md#main-gas-meter). -* Initialize the [block gas meter](../basics/04-gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. -* Run the application's [`beginBlocker()`](../basics/00-app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/05-beginblock-endblock.md#beginblock) method of each of the application's modules. -* Set the [`VoteInfos`](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_methods.md#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./02-context.md) so that it can be used during `DeliverTx` and `EndBlock`. +* Initialize the [block gas meter](../high-level-concepts/04-gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters. +* Run the application's [`beginBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../../integrate/building-modules/05-beginblock-endblock.md#beginblock) method of each of the application's modules. +* Set the [`VoteInfos`](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_methods.md#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](02-context.md) so that it can be used during `DeliverTx` and `EndBlock`. ### EndBlock -The [`EndBlock` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_basic_concepts.md#method-overview) is sent from the underlying CometBFT engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../basics/00-app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/05-beginblock-endblock.md#beginblock) method of each of the application's modules. +The [`EndBlock` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_basic_concepts.md#method-overview) is sent from the underlying CometBFT engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../high-level-concepts/00-overview-app.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../../integrate/building-modules/05-beginblock-endblock.md#beginblock) method of each of the application's modules. ### Commit @@ -503,7 +500,7 @@ The [`Info` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x/spec ### Query -The [`Query` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_basic_concepts.md#info-methods) is used to serve queries received from the underlying consensus engine, including queries received via RPC like CometBFT RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../building-modules/04-query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_app_requirements.md#query). +The [`Query` ABCI message](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_basic_concepts.md#info-methods) is used to serve queries received from the underlying consensus engine, including queries received via RPC like CometBFT RPC. It used to be the main entrypoint to build interfaces with the application, but with the introduction of [gRPC queries](../../integrate/building-modules/04-query-services.md) in Cosmos SDK v0.40, its usage is more limited. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_app_requirements.md#query). Each CometBFT `query` comes with a `path`, which is a `string` which denotes what to query. If the `path` matches a gRPC fully-qualified service method, then `BaseApp` will defer the query to the `grpcQueryRouter` and let it handle it like explained [above](#grpc-query-router). Otherwise, the `path` represents a query that is not (yet) handled by the gRPC router. `BaseApp` splits the `path` string with the `/` delimiter. By convention, the first element of the split string (`split[0]`) contains the category of `query` (`app`, `p2p`, `store` or `custom` ). The `BaseApp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving these 4 main categories of queries: diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/01-transactions.md b/versioned_docs/version-0.47/develop/advanced-concepts/01-transactions.md index 8c1fa3f9e..8b80f69ce 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/01-transactions.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/01-transactions.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 1 ---- - # Transactions :::note Synopsis @@ -12,15 +8,15 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](../basics/00-app-anatomy.md) +* [Anatomy of a Cosmos SDK Application](../high-level-concepts/00-overview-app.md) ::: ## Transactions -Transactions are comprised of metadata held in [contexts](./02-context.md) and [`sdk.Msg`s](../building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). +Transactions are comprised of metadata held in [contexts](02-context.md) and [`sdk.Msg`s](../../integrate/building-modules/02-messages-and-queries.md) that trigger state changes within a module through the module's Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md). -When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../basics/01-tx-lifecycle.md). +When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `sdk.Msg` must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../high-level-concepts/01-tx-lifecycle.md). ## Type Definition @@ -33,7 +29,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/tx_msg.go#L42-L50 It contains the following methods: * **GetMsgs:** unwraps the transaction and returns a list of contained `sdk.Msg`s - one transaction may have one or multiple messages, which are defined by module developers. -* **ValidateBasic:** lightweight, [_stateless_](../basics/01-tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./00-baseapp.md#checktx) and [`DeliverTx`](./00-baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth) module's `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from `sdk.Msg` [`ValidateBasic`](../basics/01-tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./00-baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. +* **ValidateBasic:** lightweight, [_stateless_](../high-level-concepts/01-tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](00-baseapp.md#checktx) and [`DeliverTx`](00-baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth) module's `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. When [`runTx`](00-baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself. + + :::note + This function is different from the deprecated `sdk.Msg` [`ValidateBasic`](../high-level-concepts/01-tx-lifecycle.md#ValidateBasic) methods, which was performing basic validity checks on messages only. + ::: As a developer, you should rarely manipulate `Tx` directly, as `Tx` is really an intermediate type used for transaction generation. Instead, developers should prefer the `TxBuilder` interface, which you can learn more about [below](#transaction-generation). @@ -49,7 +49,7 @@ The most used implementation of the `Tx` interface is the Protobuf `Tx` message, https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L13-L26 ``` -Because Protobuf serialization is not deterministic, the Cosmos SDK uses an additional `TxRaw` type to denote the pinned bytes over which a transaction is signed. Any user can generate a valid `body` and `auth_info` for a transaction, and serialize these two messages using Protobuf. `TxRaw` then pins the user's exact binary representation of `body` and `auth_info`, called respectively `body_bytes` and `auth_info_bytes`. The document that is signed by all signers of the transaction is `SignDoc` (deterministically serialized using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md)): +Because Protobuf serialization is not deterministic, the Cosmos SDK uses an additional `TxRaw` type to denote the pinned bytes over which a transaction is signed. Any user can generate a valid `body` and `auth_info` for a transaction, and serialize these two messages using Protobuf. `TxRaw` then pins the user's exact binary representation of `body` and `auth_info`, called respectively `body_bytes` and `auth_info_bytes`. The document that is signed by all signers of the transaction is `SignDoc` (deterministically serialized using [ADR-027](../../integrate/architecture/adr-027-deterministic-protobuf-serialization.md)): ```protobuf reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L48-L65 @@ -89,7 +89,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx The use case is a multi-signer transaction, where one of the signers is appointed to gather all signatures, broadcast the signature and pay for fees, and the others only care about the transaction body. This generally allows for a better multi-signing UX. If Alice, Bob and Charlie are part of a 3-signer transaction, then Alice and Bob can both use `SIGN_MODE_DIRECT_AUX` to sign over the `TxBody` and their own signer info (no need an additional step to gather other signers' ones, like in `SIGN_MODE_DIRECT`), without specifying a fee in their SignDoc. Charlie can then gather both signatures from Alice and Bob, and create the final transaction by appending a fee. Note that the fee payer of the transaction (in our case Charlie) must sign over the fees, so must use `SIGN_MODE_DIRECT` or `SIGN_MODE_LEGACY_AMINO_JSON`. -A concrete use case is implemented in [transaction tips](./14-tips.md): the tipper may use `SIGN_MODE_DIRECT_AUX` to specify a tip in the transaction, without signing over the actual transaction fees. Then, the fee payer appends fees inside the tipper's desired `TxBody`, and as an exchange for paying the fees and broadcasting the transaction, receives the tipper's transaction tips as payment. +A concrete use case is implemented in [transaction tips](15-tips.md): the tipper may use `SIGN_MODE_DIRECT_AUX` to specify a tip in the transaction, without signing over the actual transaction fees. Then, the fee payer appends fees inside the tipper's desired `TxBody`, and as an exchange for paying the fees and broadcasting the transaction, receives the tipper's transaction tips as payment. #### `SIGN_MODE_TEXTUAL` @@ -115,12 +115,12 @@ The next paragraphs will describe each of these components, in this order. Module `sdk.Msg`s are not to be confused with [ABCI Messages](https://docs.cometbft.com/v0.37/spec/abci/) which define interactions between the CometBFT and application layers. ::: -**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../building-modules/03-msg-services.md), and also implement the corresponding `MsgServer`. +**Messages** (or `sdk.Msg`s) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the messages for their module by adding methods to the Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md), and also implement the corresponding `MsgServer`. -Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../building-modules/03-msg-services.md) RPC, defined inside each module's `tx.proto` file. A SDK app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. +Each `sdk.Msg`s is related to exactly one Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md) RPC, defined inside each module's `tx.proto` file. A SDK app router automatically maps every `sdk.Msg` to a corresponding RPC. Protobuf generates a `MsgServer` interface for each module `Msg` service, and the module developer needs to implement this interface. This design puts more responsibility on module developers, allowing application developers to reuse common functionalities without having to implement state transition logic repetitively. -To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../building-modules/03-msg-services.md). +To learn more about Protobuf `Msg` services and how to implement `MsgServer`, click [here](../../integrate/building-modules/03-msg-services.md). While messages contain the information for state transition logic, a transaction's other metadata and relevant information are stored in the `TxBuilder` and `Context`. @@ -168,9 +168,9 @@ Once the transaction bytes are generated, there are currently three ways of broa #### CLI -Application developers create entry points to the application by creating a [command-line interface](../core/07-cli.md), [gRPC and/or REST interface](../core/06-grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. +Application developers create entry points to the application by creating a [command-line interface](07-cli.md), [gRPC and/or REST interface](09-grpc_rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line. -For the [command-line interface](../building-modules/09-module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../run-node/02-interact-node.md) section. An example transaction made using CLI looks like: +For the [command-line interface](../../integrate/building-modules/09-module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. CLI commands actually bundle all the steps of transaction processing into one simple command: creating messages, generating transactions and broadcasting. For concrete examples, see the [Interacting with a Node](../../user/run-node/02-interact-node.md) section. An example transaction made using CLI looks like: ```bash simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake @@ -178,7 +178,7 @@ simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake #### gRPC -[gRPC](https://grpc.io) is the main component for the Cosmos SDK's RPC layer. Its principal usage is in the context of modules' [`Query` services](../building-modules/04-query-services.md). However, the Cosmos SDK also exposes a few other module-agnostic gRPC services, one of them being the `Tx` service: +[gRPC](https://grpc.io) is the main component for the Cosmos SDK's RPC layer. Its principal usage is in the context of modules' [`Query` services](../../integrate/building-modules/04-query-services.md). However, the Cosmos SDK also exposes a few other module-agnostic gRPC services, one of them being the `Tx` service: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/service.proto @@ -186,13 +186,13 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/se The `Tx` service exposes a handful of utility functions, such as simulating a transaction or querying a transaction, and also one method to broadcast transactions. -Examples of broadcasting and simulating a transaction are shown [here](../run-node/03-txs.md#programmatically-with-go). +Examples of broadcasting and simulating a transaction are shown [here](../../user/run-node/03-txs.md#programmatically-with-go). #### REST Each gRPC method has its corresponding REST endpoint, generated using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). Therefore, instead of using gRPC, you can also use HTTP to broadcast the same transaction, on the `POST /cosmos/tx/v1beta1/txs` endpoint. -An example can be seen [here](../run-node/03-txs.md#using-rest) +An example can be seen [here](../../user/run-node/03-txs.md#using-rest) #### CometBFT RPC diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/02-context.md b/versioned_docs/version-0.47/develop/advanced-concepts/02-context.md index 74e4a7a24..aee982bce 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/02-context.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/02-context.md @@ -12,32 +12,32 @@ The `context` is a data structure intended to be passed from function to functio ### Pre-requisites Readings -* [Anatomy of a Cosmos SDK Application](../basics/00-app-anatomy.md) -* [Lifecycle of a Transaction](../basics/01-tx-lifecycle.md) +* [Anatomy of a Cosmos SDK Application](../high-level-concepts/00-overview-app.md) +* [Lifecycle of a Transaction](../high-level-concepts/01-tx-lifecycle.md) ::: ## Context Definition -The Cosmos SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://pkg.go.dev/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./04-store.md#base-layer-kvstores) in the [`multistore`](./04-store.md#multistore) and retrieve transactional context such as the block header and gas meter. +The Cosmos SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://pkg.go.dev/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](04-store.md#base-layer-kvstores) in the [`multistore`](04-store.md#multistore) and retrieve transactional context such as the block header and gas meter. ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/context.go#L17-L44 ``` * **Base Context:** The base type is a Go [Context](https://pkg.go.dev/context), which is explained further in the [Go Context Package](#go-context-package) section below. -* **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](./04-store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](./04-store.md#base-layer-kvstores) using their unique `StoreKey`. +* **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](04-store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](04-store.md#base-layer-kvstores) using their unique `StoreKey`. * **Header:** The [header](https://docs.cometbft.com/v0.37/spec/core/data_structures#header) is a Blockchain type. It carries important information about the state of the blockchain, such as block height and proposer of the current block. * **Header Hash:** The current block header hash, obtained during `abci.RequestBeginBlock`. * **Chain ID:** The unique identification number of the blockchain a block pertains to. -* **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the Cosmos SDK and consensus engine (e.g. CometBFT) throughout its [lifecycle](../basics/01-tx-lifecycle.md), some of which do not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./05-encoding.md) such as [Amino](./05-encoding.md). +* **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the Cosmos SDK and consensus engine (e.g. CometBFT) throughout its [lifecycle](../high-level-concepts/01-tx-lifecycle.md), some of which do not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](06-encoding.md) such as [Amino](06-encoding.md). * **Logger:** A `logger` from the CometBFT libraries. Learn more about logs [here](https://docs.cometbft.com/v0.37/core/configuration). Modules call this method to create their own unique module-specific logger. * **VoteInfo:** A list of the ABCI type [`VoteInfo`](https://docs.cometbft.com/master/spec/abci/abci.html#voteinfo), which includes the name of a validator and a boolean indicating whether they have signed the block. -* **Gas Meters:** Specifically, a [`gasMeter`](../basics/04-gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../basics/04-gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../basics/04-gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. +* **Gas Meters:** Specifically, a [`gasMeter`](../high-level-concepts/04-gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../high-level-concepts/04-gas-fees.md#block-gas-meter) for the entire block it belongs to. Users specify how much in fees they wish to pay for the execution of their transaction; these gas meters keep track of how much [gas](../high-level-concepts/04-gas-fees.md) has been used in the transaction or block so far. If the gas meter runs out, execution halts. * **CheckTx Mode:** A boolean value indicating whether a transaction should be processed in `CheckTx` or `DeliverTx` mode. -* **Min Gas Price:** The minimum [gas](../basics/04-gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. +* **Min Gas Price:** The minimum [gas](../high-level-concepts/04-gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**. * **Consensus Params:** The ABCI type [Consensus Parameters](https://docs.cometbft.com/master/spec/abci/apps.html#consensus-parameters), which specify certain limits for the blockchain, such as maximum gas for a block. -* **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](./08-events.md). Modules may define module specific +* **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](08-events.md). Modules may define module specific `Events` by defining various `Types` and `Attributes` or use the common definitions found in `types/`. Clients can subscribe or query for these `Events`. These `Events` are collected throughout `DeliverTx`, `BeginBlock`, and `EndBlock` and are returned to CometBFT for indexing. For example: * **Priority:** The transaction priority, only relevant in `CheckTx`. * **KV `GasConfig`:** Enables applications to set a custom `GasConfig` for the `KVStore`. @@ -70,14 +70,14 @@ goes wrong. The pattern of usage for a Context is as follows: 1. A process receives a Context `ctx` from its parent process, which provides information needed to perform the process. -2. The `ctx.ms` is a **branched store**, i.e. a branch of the [multistore](./04-store.md#multistore) is made so that the process can make changes to the state as it executes, without changing the original`ctx.ms`. This is useful to protect the underlying multistore in case the changes need to be reverted at some point in the execution. +2. The `ctx.ms` is a **branched store**, i.e. a branch of the [multistore](04-store.md#multistore) is made so that the process can make changes to the state as it executes, without changing the original`ctx.ms`. This is useful to protect the underlying multistore in case the changes need to be reverted at some point in the execution. 3. The process may read and write from `ctx` as it is executing. It may call a subprocess and pass `ctx` to it as needed. 4. When a subprocess returns, it checks if the result is a success or failure. If a failure, nothing needs to be done - the branch `ctx` is simply discarded. If successful, the changes made to the `CacheMultiStore` can be committed to the original `ctx.ms` via `Write()`. -For example, here is a snippet from the [`runTx`](./00-baseapp.md#runtx-antehandler-runmsgs-posthandler) function in [`baseapp`](./00-baseapp.md): +For example, here is a snippet from the [`runTx`](00-baseapp.md#runtx-antehandler-runmsgs-posthandler) function in [`baseapp`](00-baseapp.md): ```go runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes) @@ -96,7 +96,7 @@ Here is the process: 1. Prior to calling `runMsgs` on the message(s) in the transaction, it uses `app.cacheTxContext()` to branch and cache the context and multistore. 2. `runMsgCtx` - the context with branched store, is used in `runMsgs` to return a result. -3. If the process is running in [`checkTxMode`](./00-baseapp.md#checktx), there is no need to write the +3. If the process is running in [`checkTxMode`](00-baseapp.md#checktx), there is no need to write the changes - the result is returned immediately. -4. If the process is running in [`deliverTxMode`](./00-baseapp.md#delivertx) and the result indicates +4. If the process is running in [`deliverTxMode`](00-baseapp.md#delivertx) and the result indicates a successful run over all the messages, the branched multistore is written back to the original. diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/03-node.md b/versioned_docs/version-0.47/develop/advanced-concepts/03-node.md index 67eb018ca..45fd1a61e 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/03-node.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/03-node.md @@ -12,7 +12,7 @@ The main endpoint of a Cosmos SDK application is the daemon client, otherwise kn ### Pre-requisite Readings -* [Anatomy of an SDK application](../basics/00-app-anatomy.md) +* [Anatomy of an SDK application](../high-level-concepts/00-overview-app.md) ::: @@ -22,8 +22,8 @@ The full-node client of any Cosmos SDK application is built by running a `main` In general, developers will implement the `main.go` function with the following structure: -* First, an [`encodingCodec`](./05-encoding.md) is instantiated for the application. -* Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../basics/03-accounts.md#addresses). +* First, an [`encodingCodec`](06-encoding.md) is instantiated for the application. +* Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../high-level-concepts/03-accounts.md#addresses). ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/config.go#L14-L29 @@ -71,7 +71,7 @@ Note that an `appCreator` is a function that fulfills the `AppCreator` signature https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server/types/app.go#L64-L66 ``` -In practice, the [constructor of the application](../basics/00-app-anatomy.md#constructor-function) is passed as the `appCreator`. +In practice, the [constructor of the application](../high-level-concepts/00-overview-app.md#constructor-function) is passed as the `appCreator`. ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L254-L268 @@ -83,7 +83,7 @@ Then, the instance of `app` is used to instantiate a new CometBFT node: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server/start.go#L336-L348 ``` -The CometBFT node can be created with `app` because the latter satisfies the [`abci.Application` interface](https://github.com/cometbft/cometbft/blob/v0.37.0/abci/types/application.go#L9-L35) (given that `app` extends [`baseapp`](./00-baseapp.md)). As part of the `node.New` method, CometBFT makes sure that the height of the application (i.e. number of blocks since genesis) is equal to the height of the CometBFT node. The difference between these two heights should always be negative or null. If it is strictly negative, `node.New` will replay blocks until the height of the application reaches the height of the CometBFT node. Finally, if the height of the application is `0`, the CometBFT node will call [`InitChain`](./00-baseapp.md#initchain) on the application to initialize the state from the genesis file. +The CometBFT node can be created with `app` because the latter satisfies the [`abci.Application` interface](https://github.com/cometbft/cometbft/blob/v0.37.0/abci/types/application.go#L9-L35) (given that `app` extends [`baseapp`](00-baseapp.md)). As part of the `node.New` method, CometBFT makes sure that the height of the application (i.e. number of blocks since genesis) is equal to the height of the CometBFT node. The difference between these two heights should always be negative or null. If it is strictly negative, `node.New` will replay blocks until the height of the application reaches the height of the CometBFT node. Finally, if the height of the application is `0`, the CometBFT node will call [`InitChain`](00-baseapp.md#initchain) on the application to initialize the state from the genesis file. Once the CometBFT node is instantiated and in sync with the application, the node can be started: @@ -95,4 +95,4 @@ Upon starting, the node will bootstrap its RPC and P2P server and start dialing ## Other commands -To discover how to concretely run a node and interact with it, please refer to our [Running a Node, API and CLI](../run-node/01-run-node.md) guide. +To discover how to concretely run a node and interact with it, please refer to our [Running a Node, API and CLI](../../user/run-node/01-run-node.md) guide. diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/04-store.md b/versioned_docs/version-0.47/develop/advanced-concepts/04-store.md index 239cec484..1a9602dcc 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/04-store.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/04-store.md @@ -12,279 +12,94 @@ A store is a data structure that holds the state of the application. ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/00-app-anatomy.md) +* [Anatomy of a Cosmos SDK application](../high-level-concepts/00-overview-app.md) ::: -## Introduction to Cosmos SDK Stores - -The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of Cosmos SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/06-keeper.md) of the module that declared the store. - -```text -+-----------------------------------------------------+ -| | -| +--------------------------------------------+ | -| | | | -| | KVStore 1 - Manage by keeper of Module 1 | -| | | | -| +--------------------------------------------+ | -| | -| +--------------------------------------------+ | -| | | | -| | KVStore 2 - Manage by keeper of Module 2 | | -| | | | -| +--------------------------------------------+ | -| | -| +--------------------------------------------+ | -| | | | -| | KVStore 3 - Manage by keeper of Module 2 | | -| | | | -| +--------------------------------------------+ | -| | -| +--------------------------------------------+ | -| | | | -| | KVStore 4 - Manage by keeper of Module 3 | | -| | | | -| +--------------------------------------------+ | -| | -| +--------------------------------------------+ | -| | | | -| | KVStore 5 - Manage by keeper of Module 4 | | -| | | | -| +--------------------------------------------+ | -| | -| Main Multistore | -| | -+-----------------------------------------------------+ - - Application's State -``` - -### Store Interface - -At its very core, a Cosmos SDK `store` is an object that holds a `CacheWrapper` and has a `GetStoreType()` method: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L15-L18 -``` - -The `GetStoreType` is a simple method that returns the type of store, whereas a `CacheWrapper` is a simple interface that implements store read caching and write branching through `Write` method: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L260-L284 -``` - -Branching and cache is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A storage branch creates an isolated, ephemeral branch of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. Read more about it in [context](./02-context.md#Store-branching) - -### Commit Store - -A commit store is a store that has the ability to commit changes made to the underlying tree or db. The Cosmos SDK differentiates simple stores from commit stores by extending the basic store interfaces with a `Committer`: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L28-L33 -``` - -The `Committer` is an interface that defines methods to persist changes to disk: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L20-L27 -``` - -The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./10-ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`. - -The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores. +## Introduction -## Multistore - -### Multistore Interface - -Each Cosmos SDK application holds a multistore at its root to persist its state. The multistore is a store of `KVStores` that follows the `Multistore` interface: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L101-L133 -``` - -If tracing is enabled, then branching the multistore will firstly wrap all the underlying `KVStore` in [`TraceKv.Store`](#tracekv-store). - -### CommitMultiStore - -The main type of `Multistore` used in the Cosmos SDK is `CommitMultiStore`, which is an extension of the `Multistore` interface: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L141-L200 -``` - -As for concrete implementation, the [`rootMulti.Store`] is the go-to implementation of the `CommitMultiStore` interface. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/rootmulti/store.go#L53-L77 -``` - -The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./00-baseapp.md). - -### CacheMultiStore - -Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/cachemulti/store.go) is used. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/cachemulti/store.go#L19-L33 -``` - -`cachemulti.Store` branches all substores (creates a virtual store for each substore) in its constructor and hold them in `Store.stores`. Moreover caches all read queries. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on all the substores. - -## Base-layer KVStores - -### `KVStore` and `CommitKVStore` Interfaces - -A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer. - -Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/06-keeper.md) of the module that defines the store. +The Cosmos SDK store package provides interfaces, types, and abstractions for managing Merkleized state storage and commitment within a Cosmos SDK application. The package supplies various primitives for developers to work with, including state storage, state commitment, and wrapper KVStores. This document highlights the key abstractions and their significance. -`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/00-app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/store.go#L206-L239 -``` - -Apart from the traditional `Get` and `Set` methods, that a `KVStore` must implement via the `BasicKVStore` interface; a `KVStore` must provide an `Iterator(start, end)` method which returns an `Iterator` object. It is used to iterate over a range of keys, typically keys that share a common prefix. Below is an example from the bank's module keeper, used to iterate over all account balances: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/keeper/view.go#L115-L132 -``` - -### `IAVL` Store - -The default implementation of `KVStore` and `CommitKVStore` used in `baseapp` is the `iavl.Store`. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/iavl/store.go#L37-L41 -``` - -`iavl` stores are based around an [IAVL Tree](https://github.com/cosmos/iavl), a self-balancing binary tree which guarantees that: - -* `Get` and `Set` operations are O(log n), where n is the number of elements in the tree. -* Iteration efficiently returns the sorted elements within the range. -* Each tree version is immutable and can be retrieved even after a commit (depending on the pruning settings). - -The documentation on the IAVL Tree is located [here](https://github.com/cosmos/iavl/blob/master/docs/overview.md). - -### `DbAdapter` Store - -`dbadapter.Store` is a adapter for `dbm.DB` making it fulfilling the `KVStore` interface. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/dbadapter/store.go#L13-L16 -``` - -`dbadapter.Store` embeds `dbm.DB`, meaning most of the `KVStore` interface functions are implemented. The other functions (mostly miscellaneous) are manually implemented. This store is primarily used within [Transient Stores](#transient-store) - -### `Transient` Store - -`Transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/transient/store.go#L16-L19 -``` - -`Transient.Store` is a `dbadapter.Store` with a `dbm.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, a new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected. +## Multistore -This type of store is useful to persist information that is only relevant per-block. One example would be to store parameter changes (i.e. a bool set to `true` if a parameter changed in a block). +The main store in Cosmos SDK applications is a multistore, a store of stores, that supports modularity. Developers can add any number of key-value stores to the multistore based on their application needs. Each module can declare and manage its own subset of the state, allowing for a modular approach. Key-value stores within the multistore can only be accessed with a specific capability key, which is typically held in the keeper of the module that declared the store. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/params/types/subspace.go#L21-L31 -``` +## Store Interfaces -Transient stores are typically accessed via the [`context`](./02-context.md) via the `TransientStore()` method: +### KVStore -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/context.go#L284-L287 -``` +The `KVStore` interface defines a key-value store that can be used to store and retrieve data. The default implementation of `KVStore` used in `baseapp` is the `iavl.Store`, which is based on an IAVL Tree. KVStores can be accessed by objects that hold a specific key and can provide an `Iterator` method that returns an `Iterator` object, used to iterate over a range of keys. -## KVStore Wrappers +### CommitKVStore -### CacheKVStore +The `CommitKVStore` interface extends the `KVStore` interface and adds methods for state commitment. The default implementation of `CommitKVStore` used in `baseapp` is also the `iavl.Store`. -`cachekv.Store` is a wrapper `KVStore` which provides buffered writing / cached reading functionalities over the underlying `KVStore`. +### StoreDB -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/cachekv/store.go#L26-L36 -``` +The `StoreDB` interface defines a database that can be used to persist key-value stores. The default implementation of `StoreDB` used in `baseapp` is the `dbm.DB`, which is a simple persistent key-value store. -This is the type used whenever an IAVL Store needs to be branched to create an isolated store (typically when we need to mutate a state that might be reverted later). +### DBAdapter -#### `Get` +The `DBAdapter` interface defines an adapter for `dbm.DB` that fulfills the `KVStore` interface. This interface is used to provide compatibility between the `dbm.DB` implementation and the `KVStore` interface. -`Store.Get()` firstly checks if `Store.cache` has an associated value with the key. If the value exists, the function returns it. If not, the function calls `Store.parent.Get()`, caches the result in `Store.cache`, and returns it. +### TransientStore -#### `Set` +The `TransientStore` interface defines a base-layer KVStore which is automatically discarded at the end of the block and is useful for persisting information that is only relevant per-block, like storing parameter changes. -`Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field dirty bool which indicates whether the cached value is different from the underlying value. When `Store.Set()` caches a new pair, the `cValue.dirty` is set `true` so when `Store.Write()` is called it can be written to the underlying store. +## Store Abstractions -#### `Iterator` +The store package provides a comprehensive set of abstractions for managing state commitment and storage in an SDK application. These abstractions include CacheWrapping, KVStore, and CommitMultiStore, which offer a range of features such as CRUD functionality, prefix-based iteration, and state commitment management. -`Store.Iterator()` have to traverse on both cached items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPairs`, used for cached items. `mergeIterator` is a combination of two iterators, where traverse happens ordered on both iterators. +By utilizing these abstractions, developers can create modular applications with independent state management for each module. This approach allows for a more organized and maintainable application structure. -### `GasKv` Store +### CacheWrap -Cosmos SDK applications use [`gas`](../basics/04-gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications. +CacheWrap is a wrapper around a KVStore that provides caching for both read and write operations. The CacheWrap can be used to improve performance by reducing the number of disk reads and writes required for state storage operations. The CacheWrap also includes a Write method that commits the pending writes to the underlying KVStore. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/gaskv/store.go#L11-L17 -``` +### HistoryStore -When methods of the parent `KVStore` are called, `GasKv.Store` automatically consumes appropriate amount of gas depending on the `Store.gasConfig`: +The HistoryStore is an optional feature that can be used to store historical versions of the state. The HistoryStore can be used to track changes to the state over time, allowing developers to analyze changes in the state and roll back to previous versions if necessary. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/gas.go#L219-L228 -``` +### IndexStore -By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is done in the `KVStore()` method of the [`context`](./02-context.md): +The IndexStore is a type of KVStore that is used to maintain indexes of data stored in other KVStores. IndexStores can be used to improve query performance by providing a way to quickly search for data based on specific criteria. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/context.go#L279-L282 -``` +### Queryable -In this case, the gas configuration set in the `context` is used. The gas configuration can be set using the `WithKVGasConfig` method of the `context`. -Otherwise it uses the following default: +The Queryable interface is used to provide a way for applications to query the state stored in a KVStore. The Queryable interface includes methods for retrieving data based on a key or a range of keys, as well as methods for retrieving data based on specific criteria. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/types/gas.go#L230-L241 -``` +### PrefixIterator -### `TraceKv` Store +The PrefixIterator interface is used to iterate over a range of keys in a KVStore that share a common prefix. PrefixIterators can be used to efficiently retrieve subsets of data from a KVStore based on a specific prefix. -`tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`. It is applied automatically by the Cosmos SDK on all `KVStore` if tracing is enabled on the parent `MultiStore`. +### RootMultiStore -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/tracekv/store.go#L20-L43 -``` +The RootMultiStore is a Multistore that provides the ability to retrieve a snapshot of the state at a specific height. This is useful for implementing light clients. -When each `KVStore` methods are called, `tracekv.Store` automatically logs `traceOperation` to the `Store.writer`. `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. +### GasKVStore -### `Prefix` Store +The GasKVStore is a wrapper around a KVStore that provides gas measurement for read and write operations. The GasKVStore is typically used to measure the cost of executing transactions. -`prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`. +## Implementation Details -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/prefix/store.go#L15-L21 -``` +While there are many interfaces that the store package provides, there is typically a core implementation for each main interface that modules and developers interact with that are defined in the Cosmos SDK. -When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`. +The `iavl.Store` provides the core implementation for state storage and commitment by implementing the following interfaces: -When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. In that case, some of the elements are traversed even they are not starting with the prefix. +- `KVStore` +- `CommitStore` +- `CommitKVStore` +- `Queryable` +- `StoreWithInitialVersion` -### `ListenKv` Store +The `iavl.Store` also provides the ability to remove historical state from the state commitment layer. -`listenkv.Store` is a wrapper `KVStore` which provides state listening capabilities over the underlying `KVStore`. -It is applied automatically by the Cosmos SDK on any `KVStore` whose `StoreKey` is specified during state streaming configuration. -Additional information about state streaming configuration can be found in the [store/streaming/README.md](https://github.com/cosmos/cosmos-sdk/tree/v0.47.0-rc1/store/streaming). +An overview of the IAVL implementation can be found [here](https://github.com/cosmos/iavl/blob/master/docs/overview.md). -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/store/listenkv/store.go#L11-L18 -``` +Other store abstractions include `cachekv.Store`, `gaskv.Store`, `cachemulti.Store`, and `rootmulti.Store`. Each of these stores provide additional functionality and abstractions for developers to work with. -When `KVStore.Set` or `KVStore.Delete` methods are called, `listenkv.Store` automatically writes the operations to the set of `Store.listeners`. +Note that concurrent access to the `iavl.Store` tree is not safe, and it is the responsibility of the caller to ensure that concurrent access to the store is not performed. -## `BasicKVStore` interface +## Store Migration -An interface providing only the basic CRUD functionality (`Get`, `Set`, `Has`, and `Delete` methods), without iteration or caching. This is used to partially expose components of a larger store. +Store migration is the process of updating the structure of a KVStore to support new features or changes in the data model. Store migration can be a complex process, but it is essential for maintaining the integrity of the state stored in a KVStore. diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/05-interblock-cache.md b/versioned_docs/version-0.47/develop/advanced-concepts/05-interblock-cache.md new file mode 100644 index 000000000..9914c5b55 --- /dev/null +++ b/versioned_docs/version-0.47/develop/advanced-concepts/05-interblock-cache.md @@ -0,0 +1,293 @@ +--- +sidebar_position: 1 +--- + +# Inter-block Cache + +* [Inter-block Cache](#inter-block-cache) + * [Synopsis](#synopsis) + * [Overview and basic concepts](#overview-and-basic-concepts) + * [Motivation](#motivation) + * [Definitions](#definitions) + * [System model and properties](#system-model-and-properties) + * [Assumptions](#assumptions) + * [Properties](#properties) + * [Thread safety](#thread-safety) + * [Crash recovery](#crash-recovery) + * [Iteration](#iteration) + * [Technical specification](#technical-specification) + * [General design](#general-design) + * [API](#api) + * [CommitKVCacheManager](#commitkvcachemanager) + * [CommitKVStoreCache](#commitkvstorecache) + * [Implementation details](#implementation-details) + * [History](#history) + * [Copyright](#copyright) + +## Synopsis + +The inter-block cache is an in-memory cache storing (in-most-cases) immutable state that modules need to read in between blocks. When enabled, all sub-stores of a multi store, e.g., `rootmulti`, are wrapped. + +## Overview and basic concepts + +### Motivation + +The goal of the inter-block cache is to allow SDK modules to have fast access to data that it is typically queried during the execution of every block. This is data that do not change often, e.g. module parameters. The inter-block cache wraps each `CommitKVStore` of a multi store such as `rootmulti` with a fixed size, write-through cache. Caches are not cleared after a block is committed, as opposed to other caching layers such as `cachekv`. + +### Definitions + +* `Store key` uniquely identifies a store. +* `KVCache` is a `CommitKVStore` wrapped with a cache. +* `Cache manager` is a key component of the inter-block cache responsible for maintaining a map from `store keys` to `KVCaches`. + +## System model and properties + +### Assumptions + +This specification assumes that there exists a cache implementation accessible to the inter-block cache feature. + +> The implementation uses adaptive replacement cache (ARC), an enhancement over the standard last-recently-used (LRU) cache in that tracks both frequency and recency of use. + +The inter-block cache requires that the cache implementation to provide methods to create a cache, add a key/value pair, remove a key/value pair and retrieve the value associated to a key. In this specification, we assume that a `Cache` feature offers this functionality through the following methods: + +* `NewCache(size int)` creates a new cache with `size` capacity and returns it. +* `Get(key string)` attempts to retrieve a key/value pair from `Cache.` It returns `(value []byte, success bool)`. If `Cache` contains the key, it `value` contains the associated value and `success=true`. Otherwise, `success=false` and `value` should be ignored. +* `Add(key string, value []byte)` inserts a key/value pair into the `Cache`. +* `Remove(key string)` removes the key/value pair identified by `key` from `Cache`. + +The specification also assumes that `CommitKVStore` offers the following API: + +* `Get(key string)` attempts to retrieve a key/value pair from `CommitKVStore`. +* `Set(key, string, value []byte)` inserts a key/value pair into the `CommitKVStore`. +* `Delete(key string)` removes the key/value pair identified by `key` from `CommitKVStore`. + +> Ideally, both `Cache` and `CommitKVStore` should be specified in a different document and referenced here. + +### Properties + +#### Thread safety + +Accessing the `cache manager` or a `KVCache` is not thread-safe: no method is guarded with a lock. +Note that this is true even if the cache implementation is thread-safe. + +> For instance, assume that two `Set` operations are executed concurrently on the same key, each writing a different value. After both are executed, the cache and the underlying store may be inconsistent, each storing a different value under the same key. + +#### Crash recovery + +The inter-block cache transparently delegates `Commit()` to its aggregate `CommitKVStore`. If the +aggregate `CommitKVStore` supports atomic writes and use them to guarantee that the store is always in a consistent state in disk, the inter-block cache can be transparently moved to a consistent state when a failure occurs. + +> Note that this is the case for `IAVLStore`, the preferred `CommitKVStore`. On commit, it calls `SaveVersion()` on the underlying `MutableTree`. `SaveVersion` writes to disk are atomic via batching. This means that only consistent versions of the store (the tree) are written to the disk. Thus, in case of a failure during a `SaveVersion` call, on recovery from disk, the version of the store will be consistent. + +#### Iteration + +Iteration over each wrapped store is supported via the embedded `CommitKVStore` interface. + +## Technical specification + +### General design + +The inter-block cache feature is composed by two components: `CommitKVCacheManager` and `CommitKVCache`. + +`CommitKVCacheManager` implements the cache manager. It maintains a mapping from a store key to a `KVStore`. + +```go +type CommitKVStoreCacheManager interface{ + cacheSize uint + caches map[string]CommitKVStore +} +``` + +`CommitKVStoreCache` implements a `KVStore`: a write-through cache that wraps a `CommitKVStore`. This means that deletes and writes always happen to both the cache and the underlying `CommitKVStore`. Reads on the other hand first hit the internal cache. During a cache miss, the read is delegated to the underlying `CommitKVStore` and cached. + +```go +type CommitKVStoreCache interface{ + store CommitKVStore + cache Cache +} +``` + +To enable inter-block cache on `rootmulti`, one needs to instantiate a `CommitKVCacheManager` and set it by calling `SetInterBlockCache()` before calling one of `LoadLatestVersion()`, `LoadLatestVersionAndUpgrade(...)`, `LoadVersionAndUpgrade(...)` and `LoadVersion(version)`. + +### API + +#### CommitKVCacheManager + +The method `NewCommitKVStoreCacheManager` creates a new cache manager and returns it. + +| Name | Type | Description | +| ------------- | ---------|------- | +| size | integer | Determines the capacity of each of the KVCache maintained by the manager | + +```go +func NewCommitKVStoreCacheManager(size uint) CommitKVStoreCacheManager { + manager = CommitKVStoreCacheManager{size, make(map[string]CommitKVStore)} + return manager +} +``` + +`GetStoreCache` returns a cache from the CommitStoreCacheManager for a given store key. If no cache exists for the store key, then one is created and set. + +| Name | Type | Description | +| ------------- | ---------|------- | +| manager | `CommitKVStoreCacheManager` | The cache manager | +| storeKey | string | The store key of the store being retrieved | +| store | `CommitKVStore` | The store that it is cached in case the manager does not have any in its map of caches | + +```go +func GetStoreCache( + manager CommitKVStoreCacheManager, + storeKey string, + store CommitKVStore) CommitKVStore { + + if manager.caches.has(storeKey) { + return manager.caches.get(storeKey) + } else { + cache = CommitKVStoreCacheManager{store, manager.cacheSize} + manager.set(storeKey, cache) + return cache + } +} +``` + +`Unwrap` returns the underlying CommitKVStore for a given store key. + +| Name | Type | Description | +| ------------- | ---------|------- | +| manager | `CommitKVStoreCacheManager` | The cache manager | +| storeKey | string | The store key of the store being unwrapped | + +```go +func Unwrap( + manager CommitKVStoreCacheManager, + storeKey string) CommitKVStore { + + if manager.caches.has(storeKey) { + cache = manager.caches.get(storeKey) + return cache.store + } else { + return nil + } +} +``` + +`Reset` resets the manager's map of caches. + +| Name | Type | Description | +| ------------- | ---------|------- | +| manager | `CommitKVStoreCacheManager` | The cache manager | + +```go +function Reset(manager CommitKVStoreCacheManager) { + + for (let storeKey of manager.caches.keys()) { + manager.caches.delete(storeKey) + } +} +``` + +#### CommitKVStoreCache + +`NewCommitKVStoreCache` creates a new `CommitKVStoreCache` and returns it. + +| Name | Type | Description | +| ------------- | ---------|------- | +| store | CommitKVStore | The store to be cached | +| size | string | Determines the capacity of the cache being created | + +```go +func NewCommitKVStoreCache( + store CommitKVStore, + size uint) CommitKVStoreCache { + KVCache = CommitKVStoreCache{store, NewCache(size)} + return KVCache +} +``` + +`Get` retrieves a value by key. It first looks in the cache. If the key is not in the cache, the query is delegated to the underlying `CommitKVStore`. In the latter case, the key/value pair is cached. The method returns the value. + +| Name | Type | Description | +| ------------- | ---------|------- | +| KVCache | `CommitKVStoreCache` | The `CommitKVStoreCache` from which the key/value pair is retrieved | +| key | string | Key of the key/value pair being retrieved | + +```go +func Get( + KVCache CommitKVStoreCache, + key string) []byte { + valueCache, success := KVCache.cache.Get(key) + if success { + // cache hit + return valueCache + } else { + // cache miss + valueStore = KVCache.store.Get(key) + KVCache.cache.Add(key, valueStore) + return valueStore + } +} +``` + +`Set` inserts a key/value pair into both the write-through cache and the underlying `CommitKVStore`. + +| Name | Type | Description | +| ------------- | ---------|------- | +| KVCache | `CommitKVStoreCache` | The `CommitKVStoreCache` to which the key/value pair is inserted | +| key | string | Key of the key/value pair being inserted | +| value | []byte | Value of the key/value pair being inserted | + +```go +func Set( + KVCache CommitKVStoreCache, + key string, + value []byte) { + + KVCache.cache.Add(key, value) + KVCache.store.Set(key, value) +} +``` + +`Delete` removes a key/value pair from both the write-through cache and the underlying `CommitKVStore`. + +| Name | Type | Description | +| ------------- | ---------|------- | +| KVCache | `CommitKVStoreCache` | The `CommitKVStoreCache` from which the key/value pair is deleted | +| key | string | Key of the key/value pair being deleted | + +```go +func Delete( + KVCache CommitKVStoreCache, + key string) { + + KVCache.cache.Remove(key) + KVCache.store.Delete(key) +} +``` + +`CacheWrap` wraps a `CommitKVStoreCache` with another caching layer (`CacheKV`). + +> It is unclear whether there is a use case for `CacheWrap`. + +| Name | Type | Description | +| ------------- | ---------|------- | +| KVCache | `CommitKVStoreCache` | The `CommitKVStoreCache` being wrapped | + +```go +func CacheWrap( + KVCache CommitKVStoreCache) { + + return CacheKV.NewStore(KVCache) +} +``` + +### Implementation details + +The inter-block cache implementation uses a fixed-sized adaptive replacement cache (ARC) as cache. [The ARC implementation](https://github.com/hashicorp/golang-lru/blob/master/arc.go) is thread-safe. ARC is an enhancement over the standard LRU cache in that tracks both frequency and recency of use. This avoids a burst in access to new entries from evicting the frequently used older entries. It adds some additional tracking overhead to a standard LRU cache, computationally it is roughly `2x` the cost, and the extra memory overhead is linear with the size of the cache. The default cache size is `1000`. + +## History + +Dec 20, 2022 - Initial draft finished and submitted as a PR + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/05-encoding.md b/versioned_docs/version-0.47/develop/advanced-concepts/06-encoding.md similarity index 80% rename from versioned_docs/version-0.47/develop/advanced-concepts/05-encoding.md rename to versioned_docs/version-0.47/develop/advanced-concepts/06-encoding.md index 55e889f98..d26acde28 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/05-encoding.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/06-encoding.md @@ -12,7 +12,7 @@ While encoding in the Cosmos SDK used to be mainly handled by `go-amino` codec, ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/00-app-anatomy.md) +* [Anatomy of a Cosmos SDK application](../high-level-concepts/00-overview-app.md) ::: @@ -117,7 +117,7 @@ Code generators can then match the `accepts_interface` and `implements_interface ### Transaction Encoding Another important use of Protobuf is the encoding and decoding of -[transactions](./01-transactions.md). Transactions are defined by the application or +[transactions](01-transactions.md). Transactions are defined by the application or the Cosmos SDK but are then passed to the underlying consensus engine to be relayed to other peers. Since the underlying consensus engine is agnostic to the application, the consensus engine accepts only transactions in the form of raw bytes. @@ -129,7 +129,7 @@ the consensus engine accepts only transactions in the form of raw bytes. https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/tx_msg.go#L76-L80 ``` -A standard implementation of both these objects can be found in the [`auth/tx` module](../modules/auth/tx/README.md): +A standard implementation of both these objects can be found in the [`auth/tx` module](../../integrate/modules/auth/2-tx.md): ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/tx/decoder.go @@ -139,11 +139,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/tx/decoder.go https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/tx/encoder.go ``` -See [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) for details of how a transaction is encoded. +See [ADR-020](../../integrate/architecture/adr-020-protobuf-transaction-encoding.md) for details of how a transaction is encoded. ### Interface Encoding and Usage of `Any` -The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../basics/03-accounts.md): +The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../high-level-concepts/03-accounts.md): ```protobuf message Profile { @@ -154,13 +154,13 @@ message Profile { } ``` -In this `Profile` example, we hardcoded `account` as a `BaseAccount`. However, there are several other types of [user accounts related to vesting](../modules/auth/1-vesting.md), such as `BaseVestingAccount` or `ContinuousVestingAccount`. All of these accounts are different, but they all implement the `AccountI` interface. How would you create a `Profile` that allows all these types of accounts with an `account` field that accepts an `AccountI` interface? +In this `Profile` example, we hardcoded `account` as a `BaseAccount`. However, there are several other types of [user accounts related to vesting](../../integrate/modules/auth/1-vesting.md), such as `BaseVestingAccount` or `ContinuousVestingAccount`. All of these accounts are different, but they all implement the `AccountI` interface. How would you create a `Profile` that allows all these types of accounts with an `account` field that accepts an `AccountI` interface? ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/types/account.go#L307-L330 ``` -In [ADR-019](../architecture/adr-019-protobuf-state-encoding.md), it has been decided to use [`Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto)s to encode interfaces in protobuf. An `Any` contains an arbitrary serialized message as bytes, along with a URL that acts as a globally unique identifier for and resolves to that message's type. This strategy allows us to pack arbitrary Go types inside protobuf messages. Our new `Profile` then looks like: +In [ADR-019](../../integrate/architecture/adr-019-protobuf-state-encoding.md), it has been decided to use [`Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto)s to encode interfaces in protobuf. An `Any` contains an arbitrary serialized message as bytes, along with a URL that acts as a globally unique identifier for and resolves to that message's type. This strategy allows us to pack arbitrary Go types inside protobuf messages. Our new `Profile` then looks like: ```protobuf message Profile { @@ -229,7 +229,7 @@ func (p *Profile) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { The `UnpackInterfaces` gets called recursively on all structs implementing this method, to allow all `Any`s to have their `GetCachedValue()` correctly populated. -For more information about interface encoding, and especially on `UnpackInterfaces` and how the `Any`'s `type_url` gets resolved using the `InterfaceRegistry`, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). +For more information about interface encoding, and especially on `UnpackInterfaces` and how the `Any`'s `type_url` gets resolved using the `InterfaceRegistry`, please refer to [ADR-019](../../integrate/architecture/adr-019-protobuf-state-encoding.md). #### `Any` Encoding in the Cosmos SDK @@ -248,6 +248,36 @@ A real-life example of encoding the pubkey as `Any` inside the Validator struct https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/types/validator.go#L41-L64 ``` +#### `Any`'s TypeURL + +When packing a protobuf message inside an `Any`, the message's type is uniquely defined by its type URL, which is the message's fully qualified name prefixed by a `/` (slash) character. In some implementations of `Any`, like the gogoproto one, there's generally [a resolvable prefix, e.g. `type.googleapis.com`](https://github.com/gogo/protobuf/blob/b03c65ea87cdc3521ede29f62fe3ce239267c1bc/protobuf/google/protobuf/any.proto#L87-L91). However, in the Cosmos SDK, we made the decision to not include such prefix, to have shorter type URLs. The Cosmos SDK's own `Any` implementation can be found in `github.com/cosmos/cosmos-sdk/codec/types`. + +The Cosmos SDK is also switching away from gogoproto to the official `google.golang.org/protobuf` (known as the Protobuf API v2). Its default `Any` implementation also contains the [`type.googleapis.com`](https://github.com/protocolbuffers/protobuf-go/blob/v1.28.1/types/known/anypb/any.pb.go#L266) prefix. To maintain compatibility with the SDK, the following methods from `"google.golang.org/protobuf/types/known/anypb"` should not be used: + +* `anypb.New` +* `anypb.MarshalFrom` +* `anypb.Any#MarshalFrom` + +Instead, the Cosmos SDK provides helper functions in `"github.com/cosmos/cosmos-proto/anyutil"`, which create an official `anypb.Any` without inserting the prefixes: + +* `anyutil.New` +* `anyutil.MarshalFrom` + +For example, to pack a `sdk.Msg` called `internalMsg`, use: + +```diff +import ( +- "google.golang.org/protobuf/types/known/anypb" ++ "github.com/cosmos/cosmos-proto/anyutil" +) + +- anyMsg, err := anypb.New(internalMsg.Message().Interface()) ++ anyMsg, err := anyutil.New(internalMsg.Message().Interface()) + +- fmt.Println(anyMsg.TypeURL) // type.googleapis.com/cosmos.bank.v1beta1.MsgSend ++ fmt.Println(anyMsg.TypeURL) // /cosmos.bank.v1beta1.MsgSend +``` + ## FAQ ### How to create modules using protobuf encoding @@ -257,14 +287,14 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/types/validator. Protobuf types can be defined to encode: * state -* [`Msg`s](../building-modules/02-messages-and-queries.md#messages) -* [Query services](../building-modules/04-query-services.md) -* [genesis](../building-modules/08-genesis.md) +* [`Msg`s](../../integrate/building-modules/02-messages-and-queries.md#messages) +* [Query services](../../integrate/building-modules/04-query-services.md) +* [genesis](../../integrate/building-modules/08-genesis.md) #### Naming and conventions We encourage developers to follow industry guidelines: [Protocol Buffers style guide](https://developers.google.com/protocol-buffers/docs/style) -and [Buf](https://buf.build/docs/style-guide), see more details in [ADR 023](../architecture/adr-023-protobuf-naming.md) +and [Buf](https://buf.build/docs/style-guide), see more details in [ADR 023](../../integrate/architecture/adr-023-protobuf-naming.md) ### How to update modules to protobuf encoding diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/07-cli.md b/versioned_docs/version-0.47/develop/advanced-concepts/07-cli.md index e149dad67..e7bf0b428 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/07-cli.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/07-cli.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Command-Line Interface :::note Synopsis -This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../basics/00-app-anatomy.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../building-modules/01-intro.md) can be found [here](../building-modules/09-module-interfaces.md#cli). +This document describes how command-line interface (CLI) works on a high-level, for an [**application**](../high-level-concepts/00-overview-app.md). A separate document for implementing a CLI for a Cosmos SDK [**module**](../../integrate/building-modules/00-intro.md) can be found [here](../../integrate/building-modules/09-module-interfaces.md#cli). ::: ## Command-Line Interface @@ -24,12 +24,12 @@ The first four strings specify the command: * The root command for the entire application `simd`. * The subcommand `tx`, which contains all commands that let users create transactions. -* The subcommand `bank` to indicate which module to route the command to ([`x/bank`](../modules/bank/README.md) module in this case). +* The subcommand `bank` to indicate which module to route the command to ([`x/bank`](../../integrate/modules/bank/README.md) module in this case). * The type of transaction `send`. The next two strings are arguments: the `from_address` the user wishes to send from, the `to_address` of the recipient, and the `amount` they want to send. Finally, the last few strings of the command are optional flags to indicate how much the user is willing to pay in fees (calculated using the amount of gas used to execute the transaction and the gas prices provided by the user). -The CLI interacts with a [node](../core/03-node.md) to handle this command. The interface itself is defined in a `main.go` file. +The CLI interacts with a [node](03-node.md) to handle this command. The interface itself is defined in a `main.go` file. ### Building the CLI @@ -37,7 +37,7 @@ The `main.go` file needs to have a `main()` function that creates a root command * **setting configurations** by reading in configuration files (e.g. the Cosmos SDK config file). * **adding any flags** to it, such as `--chain-id`. -* **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../core/05-encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. +* **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](06-encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. * **adding subcommand** for all the possible user interactions, including [transaction commands](#transaction-commands) and [query commands](#query-commands). The `main()` function finally creates an executor and [execute](https://pkg.go.dev/github.com/spf13/cobra#Command.Execute) the root command. See an example of `main()` function from the `simapp` application: @@ -56,8 +56,8 @@ Every application CLI first constructs a root command, then adds functionality b The root command (called `rootCmd`) is what the user first types into the command line to indicate which application they wish to interact with. The string used to invoke the command (the "Use" field) is typically the name of the application suffixed with `-d`, e.g. `simd` or `gaiad`. The root command typically includes the following commands to support basic functionality in the application. -* **Status** command from the Cosmos SDK rpc client tools, which prints information about the status of the connected [`Node`](../core/03-node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. -* **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/keys) from the Cosmos SDK client tools, which includes a collection of subcommands for using the key functions in the Cosmos SDK crypto tools, including adding a new key and saving it to the keyring, listing all public keys stored in the keyring, and deleting a key. For example, users can type `simd keys add ` to add a new key and save an encrypted copy to the keyring, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](../run-node/00-keyring.md). +* **Status** command from the Cosmos SDK rpc client tools, which prints information about the status of the connected [`Node`](03-node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. +* **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/keys) from the Cosmos SDK client tools, which includes a collection of subcommands for using the key functions in the Cosmos SDK crypto tools, including adding a new key and saving it to the keyring, listing all public keys stored in the keyring, and deleting a key. For example, users can type `simd keys add ` to add a new key and save an encrypted copy to the keyring, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](../../user/run-node/00-keyring.md). * **Server** commands from the Cosmos SDK server package. These commands are responsible for providing the mechanisms necessary to start an ABCI CometBFT application and provides the CLI framework (based on [cobra](https://github.com/spf13/cobra)) necessary to fully bootstrap an application. The package exposes two core functions: `StartCmd` and `ExportCmd` which creates commands to start the application and export state respectively. Learn more [here](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server). * [**Transaction**](#transaction-commands) commands. @@ -87,7 +87,7 @@ The root-level `status` and `keys` subcommands are common across most applicatio ### Transaction Commands -[Transactions](./01-transactions.md) are objects wrapping [`Msg`s](../building-modules/02-messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCommand` is generally added to the `rootCmd`: +[Transactions](01-transactions.md) are objects wrapping [`Msg`s](../../integrate/building-modules/02-messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCommand` is generally added to the `rootCmd`: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L177-L184 @@ -95,9 +95,9 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L1 This `txCommand` function adds all the transaction available to end-users for the application. This typically includes: -* **Sign command** from the [`auth`](../modules/auth/README.md) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, the signing command is necessary for every application. +* **Sign command** from the [`auth`](../../integrate/modules/auth/README.md) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, the signing command is necessary for every application. * **Broadcast command** from the Cosmos SDK client tools, to broadcast transactions. -* **All [module transaction commands](../building-modules/09-module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddTxCommands()` function. +* **All [module transaction commands](../../integrate/building-modules/09-module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../../integrate/building-modules/01-module-manager.md#basic-manager) `AddTxCommands()` function. Here is an example of a `txCommand` aggregating these subcommands from the `simapp` application: @@ -107,7 +107,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L2 ### Query Commands -[**Queries**](../building-modules/02-messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of queries using the CLI interface, a function `queryCommand` is generally added to the `rootCmd`: +[**Queries**](../../integrate/building-modules/02-messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of queries using the CLI interface, a function `queryCommand` is generally added to the `rootCmd`: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L177-L184 @@ -119,7 +119,7 @@ This `queryCommand` function adds all the queries available to end-users for the * **Account command** from the `auth` module, which displays the state (e.g. account balance) of an account given an address. * **Validator command** from the Cosmos SDK rpc client tools, which displays the validator set of a given height. * **Block command** from the Cosmos SDK RPC client tools, which displays the block data for a given height. -* **All [module query commands](../building-modules/09-module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/01-module-manager.md#basic-manager) `AddQueryCommands()` function. +* **All [module query commands](../../integrate/building-modules/09-module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../../integrate/building-modules/01-module-manager.md#basic-manager) `AddQueryCommands()` function. Here is an example of a `queryCommand` aggregating subcommands from the `simapp` application: @@ -129,11 +129,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L2 ## Flags -Flags are used to modify commands; developers can include them in a `flags.go` file with their CLI. Users can explicitly include them in commands or pre-configure them by inside their [`app.toml`](../run-node/02-interact-node.md#configuring-the-node-using-apptoml). Commonly pre-configured flags include the `--node` to connect to and `--chain-id` of the blockchain the user wishes to interact with. +Flags are used to modify commands; developers can include them in a `flags.go` file with their CLI. Users can explicitly include them in commands or pre-configure them by inside their [`app.toml`](../../user/run-node/02-interact-node.md#configuring-the-node-using-apptoml). Commonly pre-configured flags include the `--node` to connect to and `--chain-id` of the blockchain the user wishes to interact with. A *persistent* flag (as opposed to a *local* flag) added to a command transcends all of its children: subcommands will inherit the configured values for these flags. Additionally, all flags have default values when they are added to commands; some toggle an option off but others are empty values that the user needs to override to create valid commands. A flag can be explicitly marked as *required* so that an error is automatically thrown if the user does not provide a value, but it is also acceptable to handle unexpected missing flags differently. -Flags are added to commands directly (generally in the [module's CLI file](../building-modules/09-module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a *persistent* flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. +Flags are added to commands directly (generally in the [module's CLI file](../../integrate/building-modules/09-module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a *persistent* flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. ## Environment variables @@ -168,4 +168,28 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L6 The `SetCmdClientContextHandler` call reads persistent flags via `ReadPersistentCommandFlags` which creates a `client.Context` and sets that on the root command's `Context`. -The `InterceptConfigsPreRunHandler` call creates a viper literal, default `server.Context`, and a logger and sets that on the root command's `Context`. The `server.Context` will be modified and saved to disk via the internal `interceptConfigs` call, which either reads or creates a CometBFT configuration based on the home path provided. In addition, `interceptConfigs` also reads and loads the application configuration, `app.toml`, and binds that to the `server.Context` viper literal. This is vital so the application can get access to not only the CLI flags, but also to the application configuration values provided by this file. +The `InterceptConfigsPreRunHandler` call creates a viper literal, default `server.Context`, and a logger and sets that on the root command's `Context`. The `server.Context` will be modified and saved to disk. The internal `interceptConfigs` call reads or creates a CometBFT configuration based on the home path provided. In addition, `interceptConfigs` also reads and loads the application configuration, `app.toml`, and binds that to the `server.Context` viper literal. This is vital so the application can get access to not only the CLI flags, but also to the application configuration values provided by this file. + +:::tip +When willing to configure which logger is used, do not to use `InterceptConfigsPreRunHandler`, which sets the default SDK logger, but instead use `InterceptConfigsAndCreateContext` and set the server context and the logger manually: + +```diff +-return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig) + ++serverCtx, err := server.InterceptConfigsAndCreateContext(cmd, customAppTemplate, customAppConfig, customCMTConfig) ++if err != nil { ++ return err ++} + ++// overwrite default server logger ++logger, err := server.CreateSDKLogger(serverCtx, cmd.OutOrStdout()) ++if err != nil { ++ return err ++} ++serverCtx.Logger = logger.With(log.ModuleKey, "server") + ++// set server context ++return server.SetCmdServerContext(cmd, serverCtx) +``` + +::: diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/08-events.md b/versioned_docs/version-0.47/develop/advanced-concepts/08-events.md index b07aaffd4..5011a505e 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/08-events.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/08-events.md @@ -11,7 +11,7 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK application](../basics/00-app-anatomy.md) +* [Anatomy of a Cosmos SDK application](../high-level-concepts/00-overview-app.md) * [CometBFT Documentation on Events](https://docs.cometbft.com/v0.37/spec/abci/abci++_basic_concepts#events) ::: @@ -29,25 +29,26 @@ An Event contains: * A `type` to categorize the Event at a high-level; for example, the Cosmos SDK uses the `"message"` type to filter Events by `Msg`s. * A list of `attributes` are key-value pairs that give more information about the categorized Event. For example, for the `"message"` type, we can filter Events by key-value pairs using `message.action={some_action}`, `message.module={some_module}` or `message.sender={some_sender}`. +* A `msg_index` to identify which messages relate to the same transaction :::tip To parse the attribute values as strings, make sure to add `'` (single quotes) around each attribute value. ::: -_Typed Events_ are Protobuf-defined [messages](../architecture/adr-032-typed-events.md) used by the Cosmos SDK +_Typed Events_ are Protobuf-defined [messages](../../integrate/architecture/adr-032-typed-events.md) used by the Cosmos SDK for emitting and querying Events. They are defined in a `event.proto` file, on a **per-module basis** and are read as `proto.Message`. _Legacy Events_ are defined on a **per-module basis** in the module's `/types/events.go` file. -They are triggered from the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md) +They are triggered from the module's Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md) by using the [`EventManager`](#eventmanager). In addition, each module documents its events under in the `Events` sections of its specs (x/{moduleName}/`README.md`). Lastly, Events are returned to the underlying consensus engine in the response of the following ABCI messages: -* [`BeginBlock`](./00-baseapp.md#beginblock) -* [`EndBlock`](./00-baseapp.md#endblock) -* [`CheckTx`](./00-baseapp.md#checktx) -* [`DeliverTx`](./00-baseapp.md#delivertx) +* [`BeginBlock`](00-baseapp.md#beginblock) +* [`EndBlock`](00-baseapp.md#endblock) +* [`CheckTx`](00-baseapp.md#checktx) +* [`DeliverTx`](00-baseapp.md#delivertx) ### Examples @@ -56,10 +57,9 @@ The following examples show how to query Events using the Cosmos SDK. | Event | Description | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tx.height=23` | Query all transactions at height 23 | -| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/03-msg-services.md). Note the `'`s around the value. | -| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/03-msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | +| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../../integrate/building-modules/03-msg-services.md). Note the `'`s around the value. | | `message.module='bank'` | Query all transactions containing messages from the x/bank module. Note the `'`s around the value. | -| `create_validator.validator='cosmosval1...'` | x/staking-specific Event, see [x/staking SPEC](../modules/staking/README.md). | +| `create_validator.validator='cosmosval1...'` | x/staking-specific Event, see [x/staking SPEC](../../integrate/modules/staking/README.md). | ## EventManager @@ -81,7 +81,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/events.go#L53-L62 Module developers should handle Event emission via the `EventManager#EmitTypedEvent` or `EventManager#EmitEvent` in each message `Handler` and in each `BeginBlock`/`EndBlock` handler. The `EventManager` is accessed via -the [`Context`](./02-context.md), where Event should be already registered, and emitted like this: +the [`Context`](02-context.md), where Event should be already registered, and emitted like this: **Typed events:** @@ -107,7 +107,7 @@ func NewHandler(keeper Keeper) sdk.Handler { switch msg := msg.(type) { ``` -See the [`Msg` services](../building-modules/03-msg-services.md) concept doc for a more detailed +See the [`Msg` services](../../integrate/building-modules/03-msg-services.md) concept doc for a more detailed view on how to typically implement Events and use the `EventManager` in modules. ## Subscribing to Events @@ -149,7 +149,7 @@ Subscribing to this Event would be done like so: } ``` -where `ownerAddress` is an address following the [`AccAddress`](../basics/03-accounts.md#addresses) format. +where `ownerAddress` is an address following the [`AccAddress`](../high-level-concepts/03-accounts.md#addresses) format. The same way can be used to subscribe to [legacy events](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/events.go). @@ -160,3 +160,9 @@ There are a few events that are automatically emitted for all messages, directly * `message.action`: The name of the message type. * `message.sender`: The address of the message signer. * `message.module`: The name of the module that emitted the message. + +:::tip +The module name is assumed by `baseapp` to be the second element of the message route: `"cosmos.bank.v1beta1.MsgSend" -> "bank"`. +In case a module does not follow the standard message path, (e.g. IBC), it is advised to keep emitting the module name event. +`Baseapp` only emits that event if the module have not already done so. +::: diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/06-grpc_rest.md b/versioned_docs/version-0.47/develop/advanced-concepts/09-grpc_rest.md similarity index 86% rename from versioned_docs/version-0.47/develop/advanced-concepts/06-grpc_rest.md rename to versioned_docs/version-0.47/develop/advanced-concepts/09-grpc_rest.md index 51ca4db40..f13b3a135 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/06-grpc_rest.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/09-grpc_rest.md @@ -22,15 +22,15 @@ The node also exposes some other endpoints, such as the CometBFT P2P endpoint, o ## gRPC Server -In the Cosmos SDK, Protobuf is the main [encoding](./encoding) library. This brings a wide range of Protobuf-based tools that can be plugged into the Cosmos SDK. One such tool is [gRPC](https://grpc.io), a modern open-source high performance RPC framework that has decent client support in several languages. +In the Cosmos SDK, Protobuf is the main [encoding](./06-encoding.md) library. This brings a wide range of Protobuf-based tools that can be plugged into the Cosmos SDK. One such tool is [gRPC](https://grpc.io), a modern open-source high performance RPC framework that has decent client support in several languages. -Each module exposes a [Protobuf `Query` service](../building-modules/02-messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: +Each module exposes a [Protobuf `Query` service](../../integrate/building-modules/02-messages-and-queries.md#queries) that defines state queries. The `Query` services and a transaction service used to broadcast transactions are hooked up to the gRPC server via the following function inside the application: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server/types/app.go#L46-L48 ``` -Note: It is not possible to expose any [Protobuf `Msg` service](../building-modules/02-messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programmatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../run-node/03-txs.md) for more information. +Note: It is not possible to expose any [Protobuf `Msg` service](../../integrate/building-modules/02-messages-and-queries.md#messages) endpoints via gRPC. Transactions must be generated and signed using the CLI or programmatically before they can be broadcasted using gRPC. See [Generating, Signing, and Broadcasting Transactions](../../user/run-node/03-txs.md) for more information. The `grpc.Server` is a concrete gRPC server, which spawns and serves all gRPC query requests and a broadcast transaction request. This server can be configured inside `~/.simapp/config/app.toml`: @@ -41,7 +41,7 @@ The `grpc.Server` is a concrete gRPC server, which spawns and serves all gRPC qu `~/.simapp` is the directory where the node's configuration and databases are stored. By default, it's set to `~/.{app_name}`. ::: -Once the gRPC server is started, you can send requests to it using a gRPC client. Some examples are given in our [Interact with the Node](../run-node/02-interact-node.md#using-grpc) tutorial. +Once the gRPC server is started, you can send requests to it using a gRPC client. Some examples are given in our [Interact with the Node](../../user/run-node/02-interact-node.md#using-grpc) tutorial. An overview of all available gRPC endpoints shipped with the Cosmos SDK is [Protobuf documentation](https://buf.build/cosmos/cosmos-sdk). @@ -89,7 +89,7 @@ Some CometBFT RPC endpoints are directly related to the Cosmos SDK: * `/store/{path}`: this will query the store directly. * `/p2p/filter/addr/{port}`: this will return a filtered list of the node's P2P peers by address port. * `/p2p/filter/id/{id}`: this will return a filtered list of the node's P2P peers by ID. -* `/broadcast_tx_{aync,async,commit}`: these 3 endpoint will broadcast a transaction to other peers. CLI, gRPC and REST expose [a way to broadcast transations](./01-transactions.md#broadcasting-the-transaction), but they all use these 3 CometBFT RPCs under the hood. +* `/broadcast_tx_{aync,async,commit}`: these 3 endpoint will broadcast a transaction to other peers. CLI, gRPC and REST expose [a way to broadcast transations](01-transactions.md#broadcasting-the-transaction), but they all use these 3 CometBFT RPCs under the hood. ## Comparison Table diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/09-telemetry.md b/versioned_docs/version-0.47/develop/advanced-concepts/11-telemetry.md similarity index 100% rename from versioned_docs/version-0.47/develop/advanced-concepts/09-telemetry.md rename to versioned_docs/version-0.47/develop/advanced-concepts/11-telemetry.md diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/11-runtx_middleware.md b/versioned_docs/version-0.47/develop/advanced-concepts/12-runtx_middleware.md similarity index 86% rename from versioned_docs/version-0.47/develop/advanced-concepts/11-runtx_middleware.md rename to versioned_docs/version-0.47/develop/advanced-concepts/12-runtx_middleware.md index 1db62be7a..94f5bf19b 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/11-runtx_middleware.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/12-runtx_middleware.md @@ -8,7 +8,7 @@ sidebar_position: 1 Depending on the panic type different handler is used, for instance the default one prints an error log message. Recovery middleware is used to add custom panic recovery for Cosmos SDK application developers. -More context can found in the corresponding [ADR-022](../architecture/adr-022-custom-panic-handling.md) and the implementation in [recovery.go](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/recovery.go). +More context can found in the corresponding [ADR-022](../../integrate/architecture/adr-022-custom-panic-handling.md) and the implementation in [recovery.go](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/recovery.go). ## Interface @@ -39,7 +39,7 @@ We have a module keeper that panics: func (k FooKeeper) Do(obj interface{}) { if obj == nil { // that shouldn't happen, we need to crash the app - err := sdkErrors.Wrap(fooTypes.InternalError, "obj is nil") + err := errorsmod.Wrap(fooTypes.InternalError, "obj is nil") panic(err) } } diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/12-simulation.md b/versioned_docs/version-0.47/develop/advanced-concepts/13-simulation.md similarity index 98% rename from versioned_docs/version-0.47/develop/advanced-concepts/12-simulation.md rename to versioned_docs/version-0.47/develop/advanced-concepts/13-simulation.md index ed23f3990..960bcdbbc 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/12-simulation.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/13-simulation.md @@ -97,5 +97,5 @@ Here are some suggestions when encountering a simulation failure: Learn how you can integrate the simulation into your Cosmos SDK-based application: * Application Simulation Manager -* [Building modules: Simulator](../building-modules/14-simulator.md) +* [Building modules: Simulator](../../integrate/building-modules/14-simulator.md) * Simulator tests diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/13-proto-docs.md b/versioned_docs/version-0.47/develop/advanced-concepts/14-proto-docs.md similarity index 100% rename from versioned_docs/version-0.47/develop/advanced-concepts/13-proto-docs.md rename to versioned_docs/version-0.47/develop/advanced-concepts/14-proto-docs.md diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/14-tips.md b/versioned_docs/version-0.47/develop/advanced-concepts/15-tips.md similarity index 99% rename from versioned_docs/version-0.47/develop/advanced-concepts/14-tips.md rename to versioned_docs/version-0.47/develop/advanced-concepts/15-tips.md index 2c566cfcf..7a3261233 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/14-tips.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/15-tips.md @@ -93,7 +93,7 @@ type HandlerOptions struct { // MyPostHandler returns a posthandler chain with the TipDecorator. func MyPostHandler(options HandlerOptions) (sdk.AnteHandler, error) { if options.BankKeeper == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for posthandler") + return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "bank keeper is required for posthandler") } postDecorators := []sdk.AnteDecorator{ diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/15-upgrade.md b/versioned_docs/version-0.47/develop/advanced-concepts/16-upgrade.md similarity index 96% rename from versioned_docs/version-0.47/develop/advanced-concepts/15-upgrade.md rename to versioned_docs/version-0.47/develop/advanced-concepts/16-upgrade.md index b5db25589..25b57ff86 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/15-upgrade.md +++ b/versioned_docs/version-0.47/develop/advanced-concepts/16-upgrade.md @@ -16,7 +16,7 @@ The Cosmos SDK uses two methods to perform upgrades: * Exporting the entire application state to a JSON file using the `export` CLI command, making changes, and then starting a new binary with the changed JSON file as the genesis file. -* Perform upgrades in place, which significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/13-upgrade.md) to set up your application modules to take advantage of in-place upgrades. +* Perform upgrades in place, which significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../../integrate/building-modules/13-upgrade.md) to set up your application modules to take advantage of in-place upgrades. This document provides steps to use the In-Place Store Migrations upgrade method. @@ -63,7 +63,7 @@ app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgrad }) ``` -To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../building-modules/13-upgrade.md). +To learn more about configuring migration scripts for your modules, see the [Module Upgrade Guide](../../integrate/building-modules/13-upgrade.md). ### Order Of Migrations @@ -159,4 +159,4 @@ You can sync a full node to an existing blockchain which has been upgraded using To successfully sync, you must start with the initial binary that the blockchain started with at genesis. If all Software Upgrade Plans contain binary instruction, then you can run Cosmovisor with auto-download option to automatically handle downloading and switching to the binaries associated with each sequential upgrade. Otherwise, you need to manually provide all binaries to Cosmovisor. -To learn more about Cosmovisor, see the [Cosmovisor Quick Start](../tooling/01-cosmovisor.md). +To learn more about Cosmovisor, see the [Cosmovisor Quick Start](../../integrate/tooling/01-cosmovisor.md). diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/17-config.md b/versioned_docs/version-0.47/develop/advanced-concepts/17-config.md new file mode 100644 index 000000000..03aa55a21 --- /dev/null +++ b/versioned_docs/version-0.47/develop/advanced-concepts/17-config.md @@ -0,0 +1,24 @@ +--- +sidebar_position: 1 +--- + +# Configuration + +This documentation refers to the app.toml, if you'd like to read about the config.toml please visit [CometBFT docs](https://docs.cometbft.com/v0.37/). + + +```python reference +https://github.com/cosmos/cosmos-sdk/blob/main/tools/confix/data/v0.47-app.toml +``` + +## inter-block-cache + +This feature will consume more ram than a normal node, if enabled. + +## iavl-cache-size + +Using this feature will increase ram consumption + +## iavl-lazy-loading + +This feature is to be used for archive nodes, allowing them to have a faster start up time. diff --git a/versioned_docs/version-0.47/develop/advanced-concepts/_category_.json b/versioned_docs/version-0.47/develop/advanced-concepts/_category_.json index 2a5703c28..b2ac426fb 100644 --- a/versioned_docs/version-0.47/develop/advanced-concepts/_category_.json +++ b/versioned_docs/version-0.47/develop/advanced-concepts/_category_.json @@ -1,5 +1,5 @@ { - "label": "Core Concepts", + "label": "Advanced Concepts", "position": 2, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/develop/glossary.md b/versioned_docs/version-0.47/develop/glossary.md new file mode 100644 index 000000000..c5dbfcdf2 --- /dev/null +++ b/versioned_docs/version-0.47/develop/glossary.md @@ -0,0 +1,57 @@ +--- +sidebar_position: 3 +dislayed_sidebar: developSidebar +--- + +# Glossary + +## ABCI (Application Blockchain Interface) +The interface between the Tendermint consensus engine and the application state machine, allowing them to communicate and perform state transitions. ABCI is a critical component of the Cosmos SDK, enabling developers to build applications using any programming language that can communicate via ABCI. + +## ATOM +The native staking token of the Cosmos Hub, used for securing the network, participating in governance, and paying fees for transactions. + +## CometBFT +A Byzantine Fault Tolerant (BFT) consensus engine that powers the Cosmos SDK. CometBFT is responsible for handling the consensus and networking layers of a blockchain. + +## Cosmos Hub +The first blockchain built with the Cosmos SDK, functioning as a hub for connecting other blockchains in the Cosmos ecosystem through IBC. + +## Cosmos SDK +A framework for building blockchain applications, focusing on modularity, scalability, and interoperability. + +## CosmWasm +A smart contract engine for the Cosmos SDK that enables developers to write and deploy smart contracts in WebAssembly (Wasm). CosmWasm is designed to be secure, efficient, and easy to use, allowing developers to build complex applications on top of the Cosmos SDK. + +## Delegator +A participant in a Proof of Stake network who delegates their tokens to a validator. Delegators share in the rewards and risks associated with the validator's performance in the consensus process. + +## Gas +A measure of computational effort required to execute a transaction or smart contract on a blockchain. In the Cosmos ecosystem, gas is used to meter transactions and allocate resources fairly among users. Users must pay a gas fee, usually in the native token, to have their transactions processed by the network. + +## Governance +The decision-making process in the Cosmos ecosystem, which allows token holders to propose and vote on network upgrades, parameter changes, and other critical decisions. + +## IBC (Inter-Blockchain Communication) +A protocol for secure and reliable communication between heterogeneous blockchains built on the Cosmos SDK. IBC enables the transfer of tokens and data across multiple blockchains. + +## Interoperability +The ability of different blockchains and distributed systems to communicate and interact with each other, enabling the seamless transfer of information, tokens, and other digital assets. In the context of Cosmos, the Inter-Blockchain Communication (IBC) protocol is a core technology that enables interoperability between blockchains built with the Cosmos SDK and other compatible blockchains. Interoperability allows for increased collaboration, innovation, and value creation across different blockchain ecosystems. + +## Light Clients +Lightweight blockchain clients that verify and process only a small subset of the blockchain data, allowing users to interact with the network without downloading the entire blockchain. ABCI++ aims to enhance the security and performance of light clients by enabling them to efficiently verify state transitions and proofs. + +## Module +A self-contained, reusable piece of code that can be used to build blockchain functionality within a Cosmos SDK application. Modules can be developed by the community and shared for others to use. + +## Slashing +The process of penalizing validators or delegators by reducing their staked tokens if they behave maliciously or fail to meet the network's performance requirements. + +## Staking +The process of locking up tokens as collateral to secure the network, participate in consensus, and earn rewards in a Proof of Stake (PoS) blockchain like Cosmos. + +## State Sync +A feature that allows new nodes to quickly synchronize with the current state of the blockchain without downloading and processing all previous blocks. State Sync is particularly useful for nodes that have been offline for an extended period or are joining the network for the first time. ABCI++ aims to improve the efficiency and security of State Sync. + +## Validator +A network participant responsible for proposing new blocks, validating transactions, and securing the Cosmos SDK-based blockchain through staking tokens. Validators play a crucial role in maintaining the security and integrity of the network. \ No newline at end of file diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/00-app-anatomy.md b/versioned_docs/version-0.47/develop/high-level-concepts/00-overview-app.md similarity index 62% rename from versioned_docs/version-0.47/develop/high-level-concepts/00-app-anatomy.md rename to versioned_docs/version-0.47/develop/high-level-concepts/00-overview-app.md index 482d2b4a0..96716868e 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/00-app-anatomy.md +++ b/versioned_docs/version-0.47/develop/high-level-concepts/00-overview-app.md @@ -1,8 +1,9 @@ --- sidebar_position: 1 +dislayed_sidebar: developSidebar --- -# Anatomy of a Cosmos SDK Application +# Overview of a Cosmos SDK Application :::note Synopsis This document describes the core parts of a Cosmos SDK application, represented throughout the document as a placeholder application named `app`. @@ -10,7 +11,7 @@ This document describes the core parts of a Cosmos SDK application, represented ## Node Client -The Daemon, or [Full-Node Client](../core/03-node.md), is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes, and update their state-machine as new blocks come in. +The Daemon, or [Full-Node Client](../advanced-concepts/03-node.md), is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes, and update their state-machine as new blocks come in. ```text ^ +-------------------------------+ ^ @@ -30,9 +31,9 @@ Blockchain Node | | Consensus | | v +-------------------------------+ v ``` -The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../core/03-node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). +The blockchain full-node presents itself as a binary, generally suffixed by `-d` for "daemon" (e.g. `appd` for `app` or `gaiad` for `gaia`). This binary is built by running a simple [`main.go`](../advanced-concepts/03-node.md#main-function) function placed in `./cmd/appd/`. This operation usually happens through the [Makefile](#dependencies-and-makefile). -Once the main binary is built, the node can be started by running the [`start` command](../core/03-node.md#start-command). This command function primarily does three things: +Once the main binary is built, the node can be started by running the [`start` command](../advanced-concepts/03-node.md#start-command). This command function primarily does three things: 1. Create an instance of the state-machine defined in [`app.go`](#core-application-file). 2. Initialize the state-machine with the latest known state, extracted from the `db` stored in the `~/.app/data` folder. At this point, the state-machine is at height `appBlockHeight`. @@ -50,12 +51,12 @@ In general, the core of the state-machine is defined in a file called `app.go`. The first thing defined in `app.go` is the `type` of the application. It is generally comprised of the following parts: -* **A reference to [`baseapp`](../core/00-baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by CometBFT to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://docs.cometbft.com/v0.37/spec/abci/) and the [routing logic](../core/00-baseapp.md#routing). -* **A list of store keys**. The [store](../core/04-store.md), which contains the entire state, is implemented as a [`multistore`](../core/04-store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../core/10-ocap.md) of the Cosmos SDK. -* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. -* **A reference to an [`appCodec`](../core/05-encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../core/05-encoding.md). -* **A reference to a [`legacyAmino`](../core/05-encoding.md) codec.** Some parts of the Cosmos SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicitly use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. -* **A reference to a [module manager](../building-modules/01-module-manager.md#manager)** and a [basic module manager](../building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's modules. It facilitates operations related to these modules, like registering their [`Msg` service](../core/00-baseapp.md#msg-services) and [gRPC `Query` service](../core/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). +* **A reference to [`baseapp`](../advanced-concepts/00-baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by CometBFT to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://docs.cometbft.com/v0.37/spec/abci/) and the [routing logic](../advanced-concepts/00-baseapp.md#routing). +* **A list of store keys**. The [store](../advanced-concepts/04-store.md), which contains the entire state, is implemented as a [`multistore`](../advanced-concepts/04-store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../advanced-concepts/10-ocap.md) of the Cosmos SDK. +* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../../integrate/building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions. +* **A reference to an [`appCodec`](../advanced-concepts/06-encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../advanced-concepts/06-encoding.md). +* **A reference to a [`legacyAmino`](../advanced-concepts/06-encoding.md) codec.** Some parts of the Cosmos SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicitly use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. +* **A reference to a [module manager](../../integrate/building-modules/01-module-manager.md#manager)** and a [basic module manager](../../integrate/building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's modules. It facilitates operations related to these modules, like registering their [`Msg` service](../advanced-concepts/00-baseapp.md#msg-services) and [gRPC `Query` service](../advanced-concepts/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker). See an example of application type definition from `simapp`, the Cosmos SDK's own app used for demo and testing purposes: @@ -65,7 +66,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L161-L203 ### Constructor Function -Also defined in `app.go` is the constructor function, which constructs a new application of the type defined in the preceding section. The function must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/03-node.md#start-command) of the application's daemon command. +Also defined in `app.go` is the constructor function, which constructs a new application of the type defined in the preceding section. The function must fulfill the `AppCreator` signature in order to be used in the [`start` command](../advanced-concepts/03-node.md#start-command) of the application's daemon command. ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server/types/app.go#L64-L66 @@ -73,17 +74,17 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/server/types/app.go#L64-L6 Here are the main actions performed by this function: -* Instantiate a new [`codec`](../core/05-encoding.md) and initialize the `codec` of each of the application's modules using the [basic manager](../building-modules/01-module-manager.md#basicmanager). +* Instantiate a new [`codec`](../advanced-concepts/06-encoding.md) and initialize the `codec` of each of the application's modules using the [basic manager](../../integrate/building-modules/01-module-manager.md#basicmanager). * Instantiate a new application with a reference to a `baseapp` instance, a codec, and all the appropriate store keys. * Instantiate all the [`keeper`](#keeper) objects defined in the application's `type` using the `NewKeeper` function of each of the application's modules. Note that keepers must be instantiated in the correct order, as the `NewKeeper` of one module might require a reference to another module's `keeper`. -* Instantiate the application's [module manager](../building-modules/01-module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. -* With the module manager, initialize the application's [`Msg` services](../core/00-baseapp.md#msg-services), [gRPC `Query` services](../core/00-baseapp.md#grpc-query-services), [legacy `Msg` routes](../core/00-baseapp.md#routing), and [legacy query routes](../core/00-baseapp.md#query-routing). When a transaction is relayed to the application by CometBFT via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The Cosmos SDK still supports legacy `Msg`s and legacy CometBFT queries, which are routed using the legacy `Msg` routes and the legacy query routes, respectively. -* With the module manager, register the [application's modules' invariants](../building-modules/07-invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../building-modules/07-invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry is triggered (usually the chain is halted). This is useful to make sure that no critical bug goes unnoticed, producing long-lasting effects that are hard to fix. +* Instantiate the application's [module manager](../../integrate/building-modules/01-module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. +* With the module manager, initialize the application's [`Msg` services](../advanced-concepts/00-baseapp.md#msg-services), [gRPC `Query` services](../advanced-concepts/00-baseapp.md#grpc-query-services), [legacy `Msg` routes](../advanced-concepts/00-baseapp.md#routing), and [legacy query routes](../advanced-concepts/00-baseapp.md#query-routing). When a transaction is relayed to the application by CometBFT via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The Cosmos SDK still supports legacy `Msg`s and legacy CometBFT queries, which are routed using the legacy `Msg` routes and the legacy query routes, respectively. +* With the module manager, register the [application's modules' invariants](../../integrate/building-modules/07-invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../../integrate/building-modules/07-invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry is triggered (usually the chain is halted). This is useful to make sure that no critical bug goes unnoticed, producing long-lasting effects that are hard to fix. * With the module manager, set the order of execution between the `InitGenesis`, `BeginBlocker`, and `EndBlocker` functions of each of the [application's modules](#application-module-interface). Note that not all modules implement these functions. * Set the remaining application parameters: * [`InitChainer`](#initchainer): used to initialize the application when it is first started. * [`BeginBlocker`, `EndBlocker`](#beginblocker-and-endlbocker): called at the beginning and at the end of every block. - * [`anteHandler`](../core/00-baseapp.md#antehandler): used to handle fees and signature verification. + * [`anteHandler`](../advanced-concepts/00-baseapp.md#antehandler): used to handle fees and signature verification. * Mount the stores. * Return the application. @@ -99,7 +100,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L214-L522 The `InitChainer` is a function that initializes the state of the application from a genesis file (i.e. token balances of genesis accounts). It is called when the application receives the `InitChain` message from the CometBFT engine, which happens when the node is started at `appBlockHeight == 0` (i.e. on genesis). The application must set the `InitChainer` in its [constructor](#constructor-function) via the [`SetInitChainer`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetInitChainer) method. -In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../building-modules/08-genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn calls the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../building-modules/01-module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#application-constructor), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. +In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../../integrate/building-modules/08-genesis.md#initgenesis) function of each of the application's modules. This is done by calling the `InitGenesis` function of the module manager, which in turn calls the `InitGenesis` function of each of the modules it contains. Note that the order in which the modules' `InitGenesis` functions must be called has to be set in the module manager using the [module manager's](../../integrate/building-modules/01-module-manager.md) `SetOrderInitGenesis` method. This is done in the [application's constructor](#constructor-function), and the `SetOrderInitGenesis` has to be called before the `SetInitChainer`. See an example of an `InitChainer` from `simapp`: @@ -111,9 +112,9 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L569-L577 The Cosmos SDK offers developers the possibility to implement automatic execution of code as part of their application. This is implemented through two functions called `BeginBlocker` and `EndBlocker`. They are called when the application receives the `BeginBlock` and `EndBlock` messages from the CometBFT engine, which happens respectively at the beginning and at the end of each block. The application must set the `BeginBlocker` and `EndBlocker` in its [constructor](#constructor-function) via the [`SetBeginBlocker`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetBeginBlocker) and [`SetEndBlocker`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/baseapp#BaseApp.SetEndBlocker) methods. -In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../building-modules/05-beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn calls the `BeginBlock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BeginBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods, respectively. This is done via the [module manager](../building-modules/01-module-manager.md) in the [application's constructor](#application-constructor), and the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. +In general, the `BeginBlocker` and `EndBlocker` functions are mostly composed of the [`BeginBlock` and `EndBlock`](../../integrate/building-modules/05-beginblock-endblock.md) functions of each of the application's modules. This is done by calling the `BeginBlock` and `EndBlock` functions of the module manager, which in turn calls the `BeginBlock` and `EndBlock` functions of each of the modules it contains. Note that the order in which the modules' `BeginBlock` and `EndBlock` functions must be called has to be set in the module manager using the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods, respectively. This is done via the [module manager](../../integrate/building-modules/01-module-manager.md) in the [application's constructor](#constructor-function), and the `SetOrderBeginBlockers` and `SetOrderEndBlockers` methods have to be called before the `SetBeginBlocker` and `SetEndBlocker` functions. -As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in `BeginBlocker` or `EndBlocker`, and must also be careful not to make them too computationally expensive, as [gas](./04-gas-fees.md) does not constrain the cost of `BeginBlocker` and `EndBlocker` execution. +As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in `BeginBlocker` or `EndBlocker`, and must also be careful not to make them too computationally expensive, as [gas](04-gas-fees.md) does not constrain the cost of `BeginBlocker` and `EndBlocker` execution. See an example of `BeginBlocker` and `EndBlocker` functions from `simapp` @@ -132,10 +133,10 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/params/encoding.go# Here are descriptions of what each of the four fields means: * `InterfaceRegistry`: The `InterfaceRegistry` is used by the Protobuf codec to handle interfaces that are encoded and decoded (we also say "unpacked") using [`google.protobuf.Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). `Any` could be thought as a struct that contains a `type_url` (name of a concrete type implementing the interface) and a `value` (its encoded bytes). `InterfaceRegistry` provides a mechanism for registering interfaces and implementations that can be safely unpacked from `Any`. Each application module implements the `RegisterInterfaces` method that can be used to register the module's own interfaces and implementations. - * You can read more about `Any` in [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). - * To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/cosmos/gogoproto). By default, the [gogo protobuf implementation of `Any`](https://pkg.go.dev/github.com/cosmos/gogoproto/types) uses [global type registration](https://github.com/cosmos/gogoproto/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). + * You can read more about `Any` in [ADR-019](../../integrate/architecture/adr-019-protobuf-state-encoding.md). + * To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/cosmos/gogoproto). By default, the [gogo protobuf implementation of `Any`](https://pkg.go.dev/github.com/cosmos/gogoproto/types) uses [global type registration](https://github.com/cosmos/gogoproto/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../../integrate/architecture/adr-019-protobuf-state-encoding.md). * `Codec`: The default codec used throughout the Cosmos SDK. It is composed of a `BinaryCodec` used to encode and decode state, and a `JSONCodec` used to output data to the users (for example, in the [CLI](#cli)). By default, the SDK uses Protobuf as `Codec`. -* `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/01-transactions.md). +* `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../advanced-concepts/01-transactions.md). * `Amino`: Some legacy parts of the Cosmos SDK still use Amino for backwards-compatibility. Each module exposes a `RegisterLegacyAmino` method to register the module's specific types within Amino. This `Amino` codec should not be used by app developers anymore, and will be removed in future releases. An application should create its own encoding config. @@ -147,28 +148,28 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L731-L738 ## Modules -[Modules](../building-modules/01-intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed by [`baseapp`](../core/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). +[Modules](../../integrate/building-modules/00-intro.md) are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed by [`baseapp`](../advanced-concepts/00-baseapp.md) to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. **For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application**. In the application directory, the standard practice is to store modules in the `x/` folder (not to be confused with the Cosmos SDK's `x/` folder, which contains already-built modules). ### Application Module Interface -Modules must implement [interfaces](../building-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../building-modules/01-module-manager.md#appmodulebasic) and [`AppModule`](../building-modules/01-module-manager.md#appmodule). The former implements basic non-dependent elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are, by convention, defined in a file called `module.go`. +Modules must implement [interfaces](../../integrate/building-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../../integrate/building-modules/01-module-manager.md#appmodulebasic) and [`AppModule`](../../integrate/building-modules/01-module-manager.md#appmodule). The former implements basic non-dependent elements of the module, such as the `codec`, while the latter handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are, by convention, defined in a file called `module.go`. -`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the [`module manager`](../building-modules/01-module-manager.md#manager), which manages the application's collection of modules. +`AppModule` exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the [`module manager`](../../integrate/building-modules/01-module-manager.md#manager), which manages the application's collection of modules. ### `Msg` Services Each application module defines two [Protobuf services](https://developers.google.com/protocol-buffers/docs/proto#services): one `Msg` service to handle messages, and one gRPC `Query` service to handle queries. If we consider the module as a state-machine, then a `Msg` service is a set of state transition RPC methods. Each Protobuf `Msg` service method is 1:1 related to a Protobuf request type, which must implement `sdk.Msg` interface. -Note that `sdk.Msg`s are bundled in [transactions](../core/01-transactions.md), and each transaction contains one or multiple messages. +Note that `sdk.Msg`s are bundled in [transactions](../advanced-concepts/01-transactions.md), and each transaction contains one or multiple messages. When a valid block of transactions is received by the full-node, CometBFT relays each one to the application via [`DeliverTx`](https://docs.cometbft.com/v0.37/spec/abci/abci++_app_requirements#specifics-of-responsedelivertx). Then, the application handles the transaction: 1. Upon receiving the transaction, the application first unmarshalls it from `[]byte`. -2. Then, it verifies a few things about the transaction like [fee payment and signatures](./04-gas-fees.md#antehandler) before extracting the `Msg`(s) contained in the transaction. +2. Then, it verifies a few things about the transaction like [fee payment and signatures](04-gas-fees.md#antehandler) before extracting the `Msg`(s) contained in the transaction. 3. `sdk.Msg`s are encoded using Protobuf [`Any`s](#register-codec). By analyzing each `Any`'s `type_url`, baseapp's `msgServiceRouter` routes the `sdk.Msg` to the corresponding module's `Msg` service. 4. If the message is successfully processed, the state is updated. -For more details, see [transaction lifecycle](./01-tx-lifecycle.md). +For more details, see [transaction lifecycle](01-tx-lifecycle.md). Module developers create custom `Msg` services when they build their own module. The general practice is to define the `Msg` Protobuf service in a `tx.proto` file. For example, the `x/bank` module defines a service with two methods to transfer tokens: @@ -182,7 +183,7 @@ Each module should also implement the `RegisterServices` method as part of the [ ### gRPC `Query` Services -gRPC `Query` services allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configured under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../run-node/02-interact-node.md#configuring-the-node-using-apptoml). +gRPC `Query` services allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configured under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../../user/run-node/02-interact-node.md#configuring-the-node-using-apptoml). gRPC `Query` services are defined in the module's Protobuf definition files, specifically inside `query.proto`. The `query.proto` definition file exposes a single `Query` [Protobuf service](https://developers.google.com/protocol-buffers/docs/proto#services). Each gRPC query endpoint corresponds to a service method, starting with the `rpc` keyword, inside the `Query` service. @@ -192,7 +193,7 @@ Finally, each module should also implement the `RegisterServices` method as part ### Keeper -[`Keepers`](../building-modules/06-keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../core/10-ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). +[`Keepers`](../../integrate/building-modules/06-keeper.md) are the gatekeepers of their module's store(s). To read or write in a module's store, it is mandatory to go through one of its `keeper`'s methods. This is ensured by the [object-capabilities](../advanced-concepts/10-ocap.md) model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module's `keeper` should hold the key(s) to the module's store(s). `Keepers` are generally defined in a file called `keeper.go`. It contains the `keeper`'s type definition and methods. @@ -206,14 +207,14 @@ Along with the type definition, the next important component of the `keeper.go` ### Command-Line, gRPC Services and REST Interfaces -Each module defines command-line commands, gRPC services, and REST routes to be exposed to the end-user via the [application's interfaces](#application-interfaces). This enables end-users to create messages of the types defined in the module, or to query the subset of the state managed by the module. +Each module defines command-line commands, gRPC services, and REST routes to be exposed to the end-user via the [application's interfaces](#application-interfacev). This enables end-users to create messages of the types defined in the module, or to query the subset of the state managed by the module. #### CLI -Generally, the [commands related to a module](../building-modules/09-module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands into two categories, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go`, respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): +Generally, the [commands related to a module](../../integrate/building-modules/09-module-interfaces.md#cli) are defined in a folder called `client/cli` in the module's folder. The CLI divides commands into two categories, transactions and queries, defined in `client/cli/tx.go` and `client/cli/query.go`, respectively. Both commands are built on top of the [Cobra Library](https://github.com/spf13/cobra): -* Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each [message type](#message-types) defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The Cosmos SDK handles signing and the addition of other transaction metadata. -* Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../core/00-baseapp.md#query-routing), which routes them to the appropriate [querier](#querier) the `queryRoute` parameter supplied. +* Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The Cosmos SDK handles signing and the addition of other transaction metadata. +* Queries let users query the subset of the state defined by the module. Query commands forward queries to the [application's query router](../advanced-concepts/00-baseapp.md#query-routing), which routes them to the appropriate the `queryRoute` parameter supplied. #### gRPC @@ -230,13 +231,13 @@ Some external clients may not wish to use gRPC. In this case, the Cosmos SDK pro The REST endpoints are defined in the Protobuf files, along with the gRPC services, using Protobuf annotations. Modules that want to expose REST queries should add `google.api.http` annotations to their `rpc` methods. By default, all REST endpoints defined in the SDK have a URL starting with the `/cosmos/` prefix. -The Cosmos SDK also provides a development endpoint to generate [Swagger](https://swagger.io/) definition files for these REST endpoints. This endpoint can be enabled inside the [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml) config file, under the `api.swagger` key. +The Cosmos SDK also provides a development endpoint to generate [Swagger](https://swagger.io/) definition files for these REST endpoints. This endpoint can be enabled inside the [`app.toml`](../../user/run-node/01-run-node.md#configuring-the-node-using-apptoml) config file, under the `api.swagger` key. ## Application Interface [Interfaces](#command-line-grpc-services-and-rest-interfaces) let end-users interact with full-node clients. This means querying data from the full-node or creating and sending new transactions to be relayed by the full-node and eventually included in a block. -The main interface is the [Command-Line Interface](../core/07-cli.md). The CLI of a Cosmos SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and is defined in a file called `appd/main.go`. The file contains the following: +The main interface is the [Command-Line Interface](../advanced-concepts/07-cli.md). The CLI of a Cosmos SDK application is built by aggregating [CLI commands](#cli) defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. `appd`), and is defined in a file called `appd/main.go`. The file contains the following: * **A `main()` function**, which is executed to build the `appd` interface client. This function prepares each command and adds them to the `rootCmd` before building them. At the root of `appd`, the function adds generic commands like `status`, `keys`, and `config`, query commands, tx commands, and `rest-server`. * **Query commands**, which are added by calling the `queryCmd` function. This function returns a Cobra command that contains the query commands defined in each of the application's modules (passed as an array of `sdk.ModuleClients` from the `main()` function), as well as some other lower level query commands such as block or validator queries. Query command are called by using the command `appd query [query]` of the CLI. diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/01-tx-lifecycle.md b/versioned_docs/version-0.47/develop/high-level-concepts/01-tx-lifecycle.md index ed6560772..57a3c6ff9 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/01-tx-lifecycle.md +++ b/versioned_docs/version-0.47/develop/high-level-concepts/01-tx-lifecycle.md @@ -1,24 +1,26 @@ --- sidebar_position: 1 +dislayed_sidebar: developSidebar --- # Transaction Lifecycle :::note Synopsis -This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../core/01-transactions.md). The transaction is referred to as `Tx`. +This document describes the lifecycle of a transaction from creation to committed state changes. Transaction definition is described in a [different doc](../advanced-concepts/01-transactions.md). The transaction is referred to as `Tx`. ::: :::note + ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](./00-app-anatomy.md) +* [Anatomy of a Cosmos SDK Application](00-overview-app.md) ::: ## Creation ### Transaction Creation -One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../core/07-cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: +One of the main application interfaces is the command-line interface. The transaction `Tx` can be created by the user inputting a command in the following format from the [command-line](../advanced-concepts/07-cli.md), providing the type of transaction in `[command]`, arguments in `[args]`, and configurations such as gas prices in `[flags]`: ```bash [appname] tx [command] [args] [flags] @@ -26,13 +28,13 @@ One of the main application interfaces is the command-line interface. The transa This command automatically **creates** the transaction, **signs** it using the account's private key, and **broadcasts** it to the specified peer node. -There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](./03-accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds are drawn from the specified `from` address. +There are several required and optional flags for transaction creation. The `--from` flag specifies which [account](03-accounts.md) the transaction is originating from. For example, if the transaction is sending coins, the funds are drawn from the specified `from` address. #### Gas and Fees -Additionally, there are several [flags](../core/07-cli.md) users can use to indicate how much they are willing to pay in [fees](./04-gas-fees.md): +Additionally, there are several [flags](../advanced-concepts/07-cli.md) users can use to indicate how much they are willing to pay in [fees](04-gas-fees.md): -* `--gas` refers to how much [gas](./04-gas-fees.md), which represents computational resources, `Tx` consumes. Gas is dependent on the transaction and is not precisely calculated until execution, but can be estimated by providing `auto` as the value for `--gas`. +* `--gas` refers to how much [gas](04-gas-fees.md), which represents computational resources, `Tx` consumes. Gas is dependent on the transaction and is not precisely calculated until execution, but can be estimated by providing `auto` as the value for `--gas`. * `--gas-adjustment` (optional) can be used to scale `gas` up in order to avoid underestimating. For example, users can specify their gas adjustment as 1.5 to use 1.5 times the estimated gas. * `--gas-prices` specifies how much the user is willing to pay per unit of gas, which can be one or multiple denominations of tokens. For example, `--gas-prices=0.025uatom, 0.025upho` means the user is willing to pay 0.025uatom AND 0.025upho per unit of gas. * `--fees` specifies how much in fees the user is willing to pay in total. @@ -52,7 +54,7 @@ appd tx send 1000uatom --from --gas auto --ga #### Other Transaction Creation Methods -The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../core/06-grpc_rest.md) or some other entry point defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). +The command-line is an easy way to interact with an application, but `Tx` can also be created using a [gRPC or REST interface](../advanced-concepts/09-grpc_rest.md) or some other entry point defined by the application developer. From the user's perspective, the interaction depends on the web interface or wallet they are using (e.g. creating `Tx` using [Lunie.io](https://lunie.io/#/) and signing it with a Ledger Nano S). ## Addition to Mempool @@ -72,7 +74,7 @@ are not empty, enforcing nonnegative numbers, and other logic specified in the d **_Stateful_** checks validate transactions and messages based on a committed state. Examples include checking that the relevant values exist and can be transacted with, the address has sufficient funds, and the sender is authorized or has the correct ownership to transact. -At any given moment, full-nodes typically have [multiple versions](../core/00-baseapp.md#state-updates) +At any given moment, full-nodes typically have [multiple versions](../advanced-concepts/00-baseapp.md#state-updates) of the application's internal state for different purposes. For example, nodes execute state changes while in the process of verifying transactions, but still need a copy of the last committed state in order to answer queries - they should not respond using state with uncommitted changes. @@ -83,26 +85,31 @@ through several steps, beginning with decoding `Tx`. ### Decoding -When `Tx` is received by the application from the underlying consensus engine (e.g. CometBFT ), it is still in its [encoded](../core/05-encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../core/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) function is called to run in `runTxModeCheck` mode, meaning the function runs all checks but exits before executing messages and writing state changes. +When `Tx` is received by the application from the underlying consensus engine (e.g. CometBFT ), it is still in its [encoded](../advanced-concepts/06-encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../advanced-concepts/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) function is called to run in `runTxModeCheck` mode, meaning the function runs all checks but exits before executing messages and writing state changes. -### ValidateBasic +### ValidateBasic (deprecated) -Messages ([`sdk.Msg`](../core/01-transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. -To discard obviously invalid messages, the `BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../core/00-baseapp.md#checktx) and [`DeliverTx`](../core/00-baseapp.md#delivertx) transactions. +Messages ([`sdk.Msg`](../advanced-concepts/01-transactions.md#messages)) are extracted from transactions (`Tx`). The `ValidateBasic` method of the `sdk.Msg` interface implemented by the module developer is run for each transaction. +To discard obviously invalid messages, the `BaseApp` type calls the `ValidateBasic` method very early in the processing of the message in the [`CheckTx`](../advanced-concepts/00-baseapp.md#checktx) and [`DeliverTx`](../advanced-concepts/00-baseapp.md#delivertx) transactions. `ValidateBasic` can include only **stateless** checks (the checks that do not require access to the state). -#### Guideline +:::warning +The `ValidateBasic` method on messages has been deprecated in favor of validating messages directly in their respective [`Msg` services](../../integrate/building-modules/03-msg-services.md#Validation). -Gas is not charged when `ValidateBasic` is executed, so we recommend only performing all necessary stateless checks to enable middleware operations (for example, parsing the required signer accounts to validate a signature by a middleware) and stateless sanity checks not impacting performance of the `CheckTx` phase. -Other validation operations must be performed when [handling a message](../building-modules/msg-services#Validation) in a module Msg Server. +Read [RFC 001](https://docs.cosmos.network/main/rfc/rfc-001-tx-validation) for more details. +::: -For example, if the message is to send coins from one address to another, `ValidateBasic` likely checks for non-empty addresses and a non-negative coin amount, but does not require knowledge of state such as the account balance of an address. +:::note +`BaseApp` still calls `ValidateBasic` on messages that implements that method for backwards compatibility. +::: + +#### Guideline -See also [Msg Service Validation](../building-modules/03-msg-services.md#Validation). +`ValidateBasic` should not be used anymore. Message validation should be performed in the `Msg` service when [handling a message](../../integrate/building-modules/03-msg-services#Validation) in a module Msg Server. ### AnteHandler -After the `ValidateBasic` checks, the `AnteHandler`s are run. Technically, they are optional, but in practice, they are very often present to perform signature verification, gas calculation, fee deduction, and other core operations related to blockchain transactions. +`AnteHandler`s even though optional, are in practice very often used to perform signature verification, gas calculation, fee deduction, and other core operations related to blockchain transactions. A copy of the cached context is provided to the `AnteHandler`, which performs limited checks specified for the transaction type. Using a copy allows the `AnteHandler` to do stateful checks for `Tx` without modifying the last committed state, and revert back to the original if the execution fails. @@ -110,7 +117,7 @@ For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/ ### Gas -The [`Context`](../core/02-context.md), which keeps a `GasMeter` that tracks how much gas is used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed during execution, ever exceeds `GasWanted`, the execution stops and the changes made to the cached copy of the state are not committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. +The [`Context`](../advanced-concepts/02-context.md), which keeps a `GasMeter` that tracks how much gas is used during the execution of `Tx`, is initialized. The user-provided amount of gas for `Tx` is known as `GasWanted`. If `GasConsumed`, the amount of gas consumed during execution, ever exceeds `GasWanted`, the execution stops and the changes made to the cached copy of the state are not committed. Otherwise, `CheckTx` sets `GasUsed` equal to `GasConsumed` and returns it in the result. After calculating the gas and fee values, validator-nodes check that the user-specified `gas-prices` is greater than their locally defined `min-gas-prices`. ### Discard or Addition to Mempool @@ -152,8 +159,8 @@ must be in this proposer's mempool. The next step of consensus is to execute the transactions to fully validate them. All full-nodes that receive a block proposal from the correct proposer execute the transactions by calling the ABCI functions -[`BeginBlock`](./00-app-anatomy.md#beginblocker-and-endblocker), `DeliverTx` for each transaction, -and [`EndBlock`](./00-app-anatomy.md#beginblocker-and-endblocker). While each full-node runs everything +[`BeginBlock`](00-overview-app.md#beginblocker-and-endblocker), `DeliverTx` for each transaction, +and [`EndBlock`](00-overview-app.md#beginblocker-and-endblocker). While each full-node runs everything locally, this process yields a single, unambiguous result, since the messages' state transitions are deterministic and transactions are explicitly ordered in the block proposal. @@ -196,14 +203,14 @@ explicitly ordered in the block proposal. ### DeliverTx -The `DeliverTx` ABCI function defined in [`BaseApp`](../core/00-baseapp.md) does the bulk of the +The `DeliverTx` ABCI function defined in [`BaseApp`](../advanced-concepts/00-baseapp.md) does the bulk of the state transitions: it is run for each transaction in the block in sequential order as committed to during consensus. Under the hood, `DeliverTx` is almost identical to `CheckTx` but calls the -[`runTx`](../core/00-baseapp.md#runtx) function in deliver mode instead of check mode. +[`runTx`](../advanced-concepts/00-baseapp.md#runtx) function in deliver mode instead of check mode. Instead of using their `checkState`, full-nodes use `deliverState`: * **Decoding:** Since `DeliverTx` is an ABCI call, `Tx` is received in the encoded `[]byte` form. - Nodes first unmarshal the transaction, using the [`TxConfig`](./app-anatomy#register-codec) defined in the app, then call `runTx` in `runTxModeDeliver`, which is very similar to `CheckTx` but also executes and writes state changes. + Nodes first unmarshal the transaction, using the [`TxConfig`](00-overview-app#register-codec) defined in the app, then call `runTx` in `runTxModeDeliver`, which is very similar to `CheckTx` but also executes and writes state changes. * **Checks and `AnteHandler`:** Full-nodes call `validateBasicMsgs` and `AnteHandler` again. This second check happens because they may not have seen the same transactions during the addition to Mempool stage @@ -212,14 +219,14 @@ Instead of using their `checkState`, full-nodes use `deliverState`: to each node - differing values across nodes yield nondeterministic results. * **`MsgServiceRouter`:** After `CheckTx` exits, `DeliverTx` continues to run - [`runMsgs`](../core/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) to fully execute each `Msg` within the transaction. + [`runMsgs`](../advanced-concepts/00-baseapp.md#runtx-antehandler-runmsgs-posthandler) to fully execute each `Msg` within the transaction. Since the transaction may have messages from different modules, `BaseApp` needs to know which module - to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/03-msg-services.md). - For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/01-module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/03-msg-services.md#handler-type) within the module. + to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../../integrate/building-modules/03-msg-services.md). + For `LegacyMsg` routing, the `Route` function is called via the [module manager](../../integrate/building-modules/01-module-manager.md) to retrieve the route name and find the legacy [`Handler`](../../integrate/building-modules/03-msg-services.md#handler-type) within the module. * **`Msg` service:** Protobuf `Msg` service is responsible for executing each message in the `Tx` and causes state transitions to persist in `deliverTxState`. -* **PostHandlers:** [`PostHandler`](../core/00-baseapp.md#posthandler)s run after the execution of the message. If they fail, the state change of `runMsgs`, as well of `PostHandlers`, are both reverted. +* **PostHandlers:** [`PostHandler`](../advanced-concepts/00-baseapp.md#posthandler)s run after the execution of the message. If they fail, the state change of `runMsgs`, as well of `PostHandlers`, are both reverted. * **Gas:** While a `Tx` is being delivered, a `GasMeter` is used to keep track of how much gas is being used; if execution completes, `GasUsed` is set and returned in the @@ -240,8 +247,8 @@ not they should commit the state changes. When they receive enough validator votes (2/3+ _precommits_ weighted by voting power), full nodes commit to a new block to be added to the blockchain and finalize the state transitions in the application layer. A new state root is generated to serve as -a merkle proof for the state transitions. Applications use the [`Commit`](../core/00-baseapp.md#commit) -ABCI method inherited from [Baseapp](../core/00-baseapp.md); it syncs all the state transitions by +a merkle proof for the state transitions. Applications use the [`Commit`](../advanced-concepts/00-baseapp.md#commit) +ABCI method inherited from [Baseapp](../advanced-concepts/00-baseapp.md); it syncs all the state transitions by writing the `deliverState` into the application's internal state. As soon as the state changes are committed, `checkState` starts afresh from the most recently committed state and `deliverState` resets to `nil` in order to be consistent and reflect the changes. diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/02-query-lifecycle.md b/versioned_docs/version-0.47/develop/high-level-concepts/02-query-lifecycle.md index 27db1caf4..6a3a43998 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/02-query-lifecycle.md +++ b/versioned_docs/version-0.47/develop/high-level-concepts/02-query-lifecycle.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: developSidebar --- # Query Lifecycle @@ -12,14 +13,14 @@ This document describes the lifecycle of a query in a Cosmos SDK application, fr ### Pre-requisite Readings -* [Transaction Lifecycle](./01-tx-lifecycle.md) +* [Transaction Lifecycle](01-tx-lifecycle.md) ::: ## Query Creation -A [**query**](../building-modules/02-messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../core/01-transactions.md) (view the lifecycle [here](./01-tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. +A [**query**](../../integrate/building-modules/02-messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../advanced-concepts/01-transactions.md) (view the lifecycle [here](01-tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. -For the purpose of explaining the query lifecycle, let's say the query, `MyQuery`, is requesting a list of delegations made by a certain delegator address in the application called `simapp`. As is to be expected, the [`staking`](../modules/staking/README.md) module handles this query. But first, there are a few ways `MyQuery` can be created by users. +For the purpose of explaining the query lifecycle, let's say the query, `MyQuery`, is requesting a list of delegations made by a certain delegator address in the application called `simapp`. As is to be expected, the [`staking`](../../integrate/modules/staking/README.md) module handles this query. But first, there are a few ways `MyQuery` can be created by users. ### CLI @@ -29,7 +30,7 @@ The main interface for an application is the command-line interface. Users conne simd query staking delegations ``` -This query command was defined by the [`staking`](../modules/staking/README.md) module developer and added to the list of subcommands by the application developer when creating the CLI. +This query command was defined by the [`staking`](../../integrate/modules/staking/README.md) module developer and added to the list of subcommands by the application developer when creating the CLI. Note that the general format is as follows: @@ -37,13 +38,13 @@ Note that the general format is as follows: simd query [moduleName] [command] --flag ``` -To provide values such as `--node` (the full-node the CLI connects to), the user can use the [`app.toml`](../run-node/02-interact-node.md#configuring-the-node-using-apptoml) config file to set them or provide them as flags. +To provide values such as `--node` (the full-node the CLI connects to), the user can use the [`app.toml`](../../user/run-node/02-interact-node.md#configuring-the-node-using-apptoml) config file to set them or provide them as flags. -The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../core/07-cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. +The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../advanced-concepts/07-cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. ### gRPC -Another interface through which users can make queries is [gRPC](https://grpc.io) requests to a [gRPC server](../core/06-grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. +Another interface through which users can make queries is [gRPC](https://grpc.io) requests to a [gRPC server](../advanced-concepts/09-grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. One such tool is [grpcurl](https://github.com/fullstorydev/grpcurl), and a gRPC request for `MyQuery` using this client looks like: @@ -59,7 +60,7 @@ grpcurl \ ### REST -Another interface through which users can make queries is through HTTP Requests to a [REST server](../core/06-grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). +Another interface through which users can make queries is through HTTP Requests to a [REST server](../advanced-concepts/09-grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). An example HTTP request for `MyQuery` looks like: @@ -75,10 +76,10 @@ The preceding examples show how an external user can interact with a node by que The first thing that is created in the execution of a CLI command is a `client.Context`. A `client.Context` is an object that stores all the data needed to process a request on the user side. In particular, a `client.Context` stores the following: -* **Codec**: The [encoder/decoder](../core/05-encoding.md) used by the application, used to marshal the parameters and query before making the CometBFT RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. -* **Account Decoder**: The account decoder from the [`auth`](../modules/auth/README.md) module, which translates `[]byte`s into accounts. +* **Codec**: The [encoder/decoder](../advanced-concepts/06-encoding.md) used by the application, used to marshal the parameters and query before making the CometBFT RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. +* **Account Decoder**: The account decoder from the [`auth`](../../integrate/modules/auth/README.md) module, which translates `[]byte`s into accounts. * **RPC Client**: The CometBFT RPC Client, or node, to which requests are relayed. -* **Keyring**: A [Key Manager](../basics/03-accounts.md#keyring) used to sign transactions and handle other operations with keys. +* **Keyring**: A [Key Manager](03-accounts.md#keyring) used to sign transactions and handle other operations with keys. * **Output Writer**: A [Writer](https://pkg.go.dev/io/#Writer) used to output the response. * **Configurations**: The flags configured by the user for this command, including `--height`, specifying the height of the blockchain to query, and `--indent`, which indicates to add an indent to the JSON response. @@ -96,7 +97,7 @@ At this point in the lifecycle, the user has created a CLI command with all of t #### Encoding -In our case (querying an address's delegations), `MyQuery` contains an [address](./03-accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it is ultimately relayed to a consensus engine (e.g. CometBFT) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. +In our case (querying an address's delegations), `MyQuery` contains an [address](03-accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it is ultimately relayed to a consensus engine (e.g. CometBFT) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. Here is what the code looks like for the CLI command: @@ -112,7 +113,7 @@ The Cosmos SDK leverages code generated from Protobuf services to make queries. https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/client/cli/query.go#L317-L343 ``` -Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../core/03-node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. +Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../advanced-concepts/03-node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. Here is what the code looks like: @@ -122,15 +123,15 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/query.go#L79-L113 ## RPC -With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../core/05-encoding.md) which then processes the request. Note that, while the RPC is made to the consensus engine (e.g. CometBFT) of a full-node, queries are not part of consensus and so are not broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. +With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../advanced-concepts/06-encoding.md) which then processes the request. Note that, while the RPC is made to the consensus engine (e.g. CometBFT) of a full-node, queries are not part of consensus and so are not broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. Read more about ABCI Clients and CometBFT RPC in the [CometBFT documentation](https://docs.cometbft.com/v0.37/spec/rpc/). ## Application Query Handling -When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is at that point being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../core/00-baseapp.md) implements the ABCI [`Query()`](../core/00-baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` relays the request to the relevant module. +When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is at that point being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../advanced-concepts/00-baseapp.md) implements the ABCI [`Query()`](../advanced-concepts/00-baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` relays the request to the relevant module. -Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/04-query-services.md). +Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../../integrate/building-modules/04-query-services.md). Once a result is received from the querier, `baseapp` begins the process of returning a response to the user. @@ -140,7 +141,7 @@ Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci ### CLI Response -The application [`codec`](../core/05-encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). +The application [`codec`](../advanced-concepts/06-encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/context.go#L330-L358 diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/03-accounts.md b/versioned_docs/version-0.47/develop/high-level-concepts/03-accounts.md index a9f8733ae..0d6f3624e 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/03-accounts.md +++ b/versioned_docs/version-0.47/develop/high-level-concepts/03-accounts.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: developSidebar --- # Accounts @@ -12,13 +13,13 @@ This document describes the in-built account and public key system of the Cosmos ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](./00-app-anatomy.md) +* [Anatomy of a Cosmos SDK Application](00-overview-app.md) ::: ## Account Definition -In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/02-messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. +In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../../integrate/building-modules/02-messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#keys-accounts-addresses-and-signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The BIP32 allows users to create an HD wallet (as specified in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. A single seed can derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. @@ -153,7 +154,7 @@ The default implementation of `Keyring` comes from the third-party [`99designs/k A few notes on the `Keyring` methods: -* `Sign(uid string, msg []byte) ([]byte, types.PubKey, error)` strictly deals with the signature of the `msg` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`anteHandler`](../core/00-baseapp.md#antehandler). +* `Sign(uid string, msg []byte) ([]byte, types.PubKey, error)` strictly deals with the signature of the `msg` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../../integrate/architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../../integrate/architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`anteHandler`](../advanced-concepts/00-baseapp.md#antehandler). ```protobuf reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L48-L65 @@ -199,7 +200,7 @@ First a new function to create a private key from a secret number is needed in t func NewPrivKeyFromSecret(secret []byte) (*PrivKey, error) { var d = new(big.Int).SetBytes(secret) if d.Cmp(secp256r1.Params().N) >= 1 { - return nil, sdkerrors.Wrap(errors.ErrInvalidRequest, "secret not in the curve base field") + return nil, errorsmod.Wrap(errors.ErrInvalidRequest, "secret not in the curve base field") } sk := new(ecdsa.PrivKey) return &PrivKey{&ecdsaSK{*sk}}, nil diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/04-gas-fees.md b/versioned_docs/version-0.47/develop/high-level-concepts/04-gas-fees.md index 821fe9711..f63775b11 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/04-gas-fees.md +++ b/versioned_docs/version-0.47/develop/high-level-concepts/04-gas-fees.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: developSidebar --- # Gas and Fees @@ -12,7 +13,7 @@ This document describes the default strategies to handle gas and fees within a C ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](./00-app-anatomy.md) +* [Anatomy of a Cosmos SDK Application](00-overview-app.md) ::: @@ -21,7 +22,7 @@ This document describes the default strategies to handle gas and fees within a C In the Cosmos SDK, `gas` is a special unit that is used to track the consumption of resources during execution. `gas` is typically consumed whenever read and writes are made to the store, but it can also be consumed if expensive computation needs to be done. It serves two main purposes: * Make sure blocks are not consuming too many resources and are finalized. This is implemented by default in the Cosmos SDK via the [block gas meter](#block-gas-meter). -* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/02-messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications implement `fee` mechanisms to prevent spam by using the [`AnteHandler`](#antehandler). +* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../../integrate/building-modules/02-messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications implement `fee` mechanisms to prevent spam by using the [`AnteHandler`](#antehandler). ## Gas Meter @@ -42,29 +43,29 @@ where: * `IsPastLimit()` returns `true` if the amount of gas consumed by the gas meter instance is strictly above the limit, `false` otherwise. * `IsOutOfGas()` returns `true` if the amount of gas consumed by the gas meter instance is above or equal to the limit, `false` otherwise. -The gas meter is generally held in [`ctx`](../core/02-context.md), and consuming gas is done with the following pattern: +The gas meter is generally held in [`ctx`](../advanced-concepts/02-context.md), and consuming gas is done with the following pattern: ```go ctx.GasMeter().ConsumeGas(amount, "description") ``` -By default, the Cosmos SDK makes use of two different gas meters, the [main gas meter](#main-gas-metter) and the [block gas meter](#block-gas-meter). +By default, the Cosmos SDK makes use of two different gas meters, the [main gas meter](#main-gas-meter) and the [block gas meter](#block-gas-meter). ### Main Gas Meter -`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../core/00-baseapp.md#beginblock), [`DeliverTx`](../core/00-baseapp.md#delivertx) and [`EndBlock`](../core/00-baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. +`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../advanced-concepts/00-baseapp.md#beginblock), [`DeliverTx`](../advanced-concepts/00-baseapp.md#delivertx) and [`EndBlock`](../advanced-concepts/00-baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction. -Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/05-beginblock-endblock.md) or [`Msg` service](../building-modules/03-msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../core/04-store.md#gaskv-store). +Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../../integrate/building-modules/05-beginblock-endblock.md) or [`Msg` service](../../integrate/building-modules/03-msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../advanced-concepts/04-store.md#gaskv-store). ### Block Gas Meter -`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../core/00-baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default, Cosmos SDK applications use the default consensus parameters provided by CometBFT: +`ctx.BlockGasMeter()` is the gas meter used to track gas consumption per block and make sure it does not go above a certain limit. A new instance of the `BlockGasMeter` is created each time [`BeginBlock`](../advanced-concepts/00-baseapp.md#beginblock) is called. The `BlockGasMeter` is finite, and the limit of gas per block is defined in the application's consensus parameters. By default, Cosmos SDK applications use the default consensus parameters provided by CometBFT: ```go reference https://github.com/cometbft/cometbft/blob/v0.37.0/types/params.go#L66-L105 ``` -When a new [transaction](../core/01-transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: +When a new [transaction](../advanced-concepts/01-transactions.md) is being processed via `DeliverTx`, the current value of `BlockGasMeter` is checked to see if it is above the limit. If it is, `DeliverTx` returns immediately. This can happen even with the first transaction in a block, as `BeginBlock` itself can consume gas. If not, the transaction is processed normally. At the end of `DeliverTx`, the gas tracked by `ctx.BlockGasMeter()` is increased by the amount consumed to process the transaction: ```go ctx.BlockGasMeter().ConsumeGas( @@ -91,9 +92,9 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/tx_msg.go#L42-L50 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L13-L26 ``` -* Verify signatures for each [`message`](../building-modules/02-messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. +* Verify signatures for each [`message`](../../integrate/building-modules/02-messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`. * During `CheckTx`, verify that the gas prices provided with the transaction is greater than the local `min-gas-prices` (as a reminder, gas-prices can be deducted from the following equation: `fees = gas * gas-prices`). `min-gas-prices` is a parameter local to each full-node and used during `CheckTx` to discard transactions that do not provide a minimum amount of fees. This ensures that the mempool cannot be spammed with garbage transactions. * Verify that the sender of the transaction has enough funds to cover for the `fees`. When the end-user generates a transaction, they must indicate 2 of the 3 following parameters (the third one being implicit): `fees`, `gas` and `gas-prices`. This signals how much they are willing to pay for nodes to execute their transaction. The provided `gas` value is stored in a parameter called `GasWanted` for later use. * Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is crucial**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx` is set to `newCtx` after `anteHandler` is run, and the `anteHandler` is run each time `DeliverTx` is called). -As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../core/00-baseapp.md#delivertx) returns. +As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../advanced-concepts/00-baseapp.md#delivertx) returns. diff --git a/versioned_docs/version-0.47/develop/high-level-concepts/_category_.json b/versioned_docs/version-0.47/develop/high-level-concepts/_category_.json index 1f2b57293..2c4105ee6 100644 --- a/versioned_docs/version-0.47/develop/high-level-concepts/_category_.json +++ b/versioned_docs/version-0.47/develop/high-level-concepts/_category_.json @@ -1,5 +1,5 @@ { - "label": "Basics", + "label": "High Level Concepts", "position": 1, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/develop/intro/00-what-is-sdk.md b/versioned_docs/version-0.47/develop/intro/00-what-is-sdk.md index cb14ee46a..9106ad886 100644 --- a/versioned_docs/version-0.47/develop/intro/00-what-is-sdk.md +++ b/versioned_docs/version-0.47/develop/intro/00-what-is-sdk.md @@ -2,11 +2,12 @@ sidebar_position: 0 dislayed_sidebar: developSidebar --- + # What is the Cosmos SDK The [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is an open-source framework for building multi-asset public Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as permissioned Proof-of-Authority (PoA) blockchains. Blockchains built with the Cosmos SDK are generally referred to as **application-specific blockchains**. -The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the Cosmos SDK as the npm-like framework to build secure blockchain applications on top of [CometBFT](https://github.com/cometbft/cometbft). SDK-based blockchains are built out of composable [modules](../building-modules/01-intro.md), most of which are open-source and readily available for any developers to use. Anyone can create a module for the Cosmos SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system that allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [Object-Capability Model](../core/10-ocap.md). +The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. We envision the Cosmos SDK as the npm-like framework to build secure blockchain applications on top of [CometBFT](https://github.com/cometbft/cometbft). SDK-based blockchains are built out of composable [modules](../../integrate/building-modules/00-intro.md), most of which are open-source and readily available for any developers to use. Anyone can create a module for the Cosmos SDK, and integrating already-built modules is as simple as importing them into your blockchain application. What's more, the Cosmos SDK is a capabilities-based system that allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [Object-Capability Model](../advanced-concepts/10-ocap.md). ## What are Application-Specific Blockchains @@ -14,18 +15,18 @@ One development paradigm in the blockchain world today is that of virtual-machin Application-specific blockchains offer a radically different development paradigm than virtual-machine blockchains. An application-specific blockchain is a blockchain customized to operate a single application: developers have all the freedom to make the design decisions required for the application to run optimally. They can also provide better sovereignty, security and performance. -Learn more about [application-specific blockchains](./01-why-app-specific.md). +Learn more about [application-specific blockchains](01-why-app-specific.md). ## Why the Cosmos SDK The Cosmos SDK is the most advanced framework for building custom application-specific blockchains today. Here are a few reasons why you might want to consider building your decentralized application with the Cosmos SDK: * The default consensus engine available within the Cosmos SDK is [CometBFT](https://github.com/cometbft/cometbft). CometBFT is the most (and only) mature BFT consensus engine in existence. It is widely used across the industry and is considered the gold standard consensus engine for building Proof-of-Stake systems. -* The Cosmos SDK is open-source and designed to make it easy to build blockchains out of composable [modules](../modules). As the ecosystem of open-source Cosmos SDK modules grows, it will become increasingly easier to build complex decentralized platforms with it. +* The Cosmos SDK is open-source and designed to make it easy to build blockchains out of composable [modules](../../integrate/modules). As the ecosystem of open-source Cosmos SDK modules grows, it will become increasingly easier to build complex decentralized platforms with it. * The Cosmos SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. This makes the Cosmos SDK a very secure environment to build blockchains. * Most importantly, the Cosmos SDK has already been used to build many application-specific blockchains that are already in production. Among others, we can cite [Cosmos Hub](https://hub.cosmos.network), [IRIS Hub](https://irisnet.org), [Binance Chain](https://docs.binance.org/), [Terra](https://terra.money/) or [Kava](https://www.kava.io/). [Many more](https://cosmos.network/ecosystem) are building on the Cosmos SDK. ## Getting started with the Cosmos SDK -* Learn more about the [architecture of a Cosmos SDK application](./02-sdk-app-architecture.md) +* Learn more about the [architecture of a Cosmos SDK application](02-sdk-app-architecture.md) * Learn how to build an application-specific blockchain from scratch with the [Cosmos SDK Tutorial](https://cosmos.network/docs/tutorial) diff --git a/versioned_docs/version-0.47/develop/intro/02-sdk-app-architecture.md b/versioned_docs/version-0.47/develop/intro/02-sdk-app-architecture.md index a7ef4fa7a..54c8eb4b5 100644 --- a/versioned_docs/version-0.47/develop/intro/02-sdk-app-architecture.md +++ b/versioned_docs/version-0.47/develop/intro/02-sdk-app-architecture.md @@ -3,7 +3,7 @@ sidebar_position: 0 dislayed_sidebar: developSidebar --- -# Blockchain Architecture +# Introduction to Blockchain Architecture ## State machine @@ -85,10 +85,10 @@ Note that **CometBFT only handles transaction bytes**. It has no knowledge of wh Here are the most important messages of the ABCI: -* `CheckTx`: When a transaction is received by CometBFT, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. . A special handler called the [`AnteHandler`](../basics/04-gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.cometbft.com/v0.37/spec/p2p/messages/mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. -* `DeliverTx`: When a [valid block](https://docs.cometbft.com/v0.37/spec/core/data_structures#block) is received by CometBFT, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again, along with the actual [`Msg` service](../building-modules/03-msg-services.md) RPC for each message in the transaction. +* `CheckTx`: When a transaction is received by CometBFT, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. . A special handler called the [`AnteHandler`](../high-level-concepts/04-gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.cometbft.com/v0.37/spec/p2p/messages/mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +* `DeliverTx`: When a [valid block](https://docs.cometbft.com/v0.37/spec/core/data_structures#block) is received by CometBFT, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again, along with the actual [`Msg` service](../../integrate/building-modules/03-msg-services.md) RPC for each message in the transaction. * `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transactions or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. Find a more detailed view of the ABCI methods from the [CometBFT docs](https://docs.cometbft.com/v0.37/spec/abci/). -Any application built on CometBFT needs to implement the ABCI interface in order to communicate with the underlying local CometBFT engine. Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of [baseapp](./03-sdk-design.md#baseapp). +Any application built on CometBFT needs to implement the ABCI interface in order to communicate with the underlying local CometBFT engine. Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of [baseapp](03-sdk-design.md#baseapp). diff --git a/versioned_docs/version-0.47/develop/intro/03-sdk-design.md b/versioned_docs/version-0.47/develop/intro/03-sdk-design.md index 6a8bc52de..f70f51867 100644 --- a/versioned_docs/version-0.47/develop/intro/03-sdk-design.md +++ b/versioned_docs/version-0.47/develop/intro/03-sdk-design.md @@ -5,7 +5,7 @@ dislayed_sidebar: developSidebar # Main Components of the Cosmos SDK -The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of CometBFT. At its core, the Cosmos SDK is a boilerplate implementation of the [ABCI](./02-sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../core/04-store.md#multistore) to persist data and a [`router`](../core/00-baseapp.md#routing) to handle transactions. +The Cosmos SDK is a framework that facilitates the development of secure state-machines on top of CometBFT. At its core, the Cosmos SDK is a boilerplate implementation of the [ABCI](02-sdk-app-architecture.md#abci) in Golang. It comes with a [`multistore`](../advanced-concepts/04-store.md#multistore) to persist data and a [`router`](../advanced-concepts/00-baseapp.md#routing) to handle transactions. Here is a simplified view of how transactions are handled by an application built on top of the Cosmos SDK when transferred from CometBFT via `DeliverTx`: @@ -16,7 +16,7 @@ Here is a simplified view of how transactions are handled by an application buil ## `baseapp` -`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../basics/00-app-anatomy.md#core-application-file). +`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../high-level-concepts/00-overview-app.md#core-application-file). Here is an example of this from `simapp`, the Cosmos SDK demonstration app: @@ -26,13 +26,13 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go#L164-L203 The goal of `baseapp` is to provide a secure interface between the store and the extensible state machine while defining as little about the state machine as possible (staying true to the ABCI). -For more on `baseapp`, please click [here](../core/00-baseapp.md). +For more on `baseapp`, please click [here](../advanced-concepts/00-baseapp.md). ## Multistore -The Cosmos SDK provides a [`multistore`](../core/04-store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../core/04-store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../core/05-encoding.md) before being stored. +The Cosmos SDK provides a [`multistore`](../advanced-concepts/04-store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../advanced-concepts/04-store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../advanced-concepts/06-encoding.md) before being stored. -The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../core/04-store.md#multistore) +The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../advanced-concepts/04-store.md#multistore) ## Modules @@ -85,7 +85,7 @@ Here is a simplified view of how a transaction is processed by the application o v ``` -Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../core/10-ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. +Each module can be seen as a little state-machine. Developers need to define the subset of the state handled by the module, as well as custom message types that modify the state (*Note:* `messages` are extracted from `transactions` by `baseapp`). In general, each module declares its own `KVStore` in the `multistore` to persist the subset of the state it defines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos SDK is an open framework, some of the modules may be malicious, which means there is a need for security principles to reason about inter-module interactions. These principles are based on [object-capabilities](../advanced-concepts/10-ocap.md). In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called `keepers` that can be passed to other modules to grant a pre-defined set of capabilities. Cosmos SDK modules are defined in the `x/` folder of the Cosmos SDK. Some core modules include: diff --git a/versioned_docs/version-0.47/integrate/_category_.json b/versioned_docs/version-0.47/integrate/_category_.json new file mode 100644 index 000000000..b860342f4 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Integrate", + "position": 0, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/architecture/PROCESS.md b/versioned_docs/version-0.47/integrate/architecture/PROCESS.md index c5140bbe4..e30a74062 100644 --- a/versioned_docs/version-0.47/integrate/architecture/PROCESS.md +++ b/versioned_docs/version-0.47/integrate/architecture/PROCESS.md @@ -3,24 +3,26 @@ 1. Copy the `adr-template.md` file. Use the following filename pattern: `adr-next_number-title.md` 2. Create a draft Pull Request if you want to get an early feedback. 3. Make sure the context and a solution is clear and well documented. -4. Add an entry to a list in the [README](./README.md) file. +4. Add an entry to a list in the [README](README.md) file. 5. Create a Pull Request to propose a new ADR. -## ADR life cycle +## What is an ADR? + +An ADR is a document to document an implementation and design that may or may not have been discussed in an RFC. While an RFC is meant to replace synchoronus communication in a distributed environment, an ADR is meant to document an already made decision. An ADR wont come with much of a communication overhead because the discussion was recorded in an RFC or a synchronous discussion. If the consensus came from a synchoronus discussion then a short excerpt should be added to the ADR to explain the goals. -ADR creation is an **iterative** process. Instead of trying to solve all decisions in a single ADR pull request, we MUST firstly understand the problem and collect feedback through a GitHub Issue. +## ADR life cycle -1. Every proposal SHOULD start with a new GitHub Issue or be a result of existing Issues. The Issue should contain just a brief proposal summary. +ADR creation is an **iterative** process. Instead of having a high amount of communication overhead, an ADR is used when there is already a decision made and implementation details need to be added. The ADR should document what the collective consensus for the specific issue is and how to solve it. -2. Once the motivation is validated, a GitHub Pull Request (PR) is created with a new document based on the `adr-template.md`. +1. Every ADR should start with either an RFC or discussion where consensus has been met. -3. An ADR doesn't have to arrive to `main` with an _accepted_ status in a single PR. If the motivation is clear and the solution is sound, we SHOULD be able to merge it and keep a _proposed_ status. It's preferable to have an iterative approach rather than long, not merged Pull Requests. +2. Once consensus is met, a GitHub Pull Request (PR) is created with a new document based on the `adr-template.md`. -4. If a _proposed_ ADR is merged, then it should clearly document outstanding issues either in ADR document notes or in a GitHub Issue. +3. If a _proposed_ ADR is merged, then it should clearly document outstanding issues either in ADR document notes or in a GitHub Issue. -5. The PR SHOULD always be merged. In the case of a faulty ADR, we still prefer to merge it with a _rejected_ status. The only time the ADR SHOULD NOT be merged is if the author abandons it. +4. The PR SHOULD always be merged. In the case of a faulty ADR, we still prefer to merge it with a _rejected_ status. The only time the ADR SHOULD NOT be merged is if the author abandons it. -6. Merged ADRs SHOULD NOT be pruned. +5. Merged ADRs SHOULD NOT be pruned. ### ADR status diff --git a/versioned_docs/version-0.47/integrate/architecture/README.md b/versioned_docs/version-0.47/integrate/architecture/README.md index ee65454da..ce1ee432d 100644 --- a/versioned_docs/version-0.47/integrate/architecture/README.md +++ b/versioned_docs/version-0.47/integrate/architecture/README.md @@ -32,7 +32,7 @@ If recorded decisions turned out to be lacking, convene a discussion, record the ## Creating new ADR -Read about the [PROCESS](./PROCESS.md). +Read about the [PROCESS](PROCESS.md). ### Use RFC 2119 Keywords @@ -42,48 +42,53 @@ When writing ADRs, follow the same best practices for writing RFCs. When writing ### Accepted -* [ADR 002: SDK Documentation Structure](./adr-002-docs-structure.md) -* [ADR 004: Split Denomination Keys](./adr-004-split-denomination-keys.md) -* [ADR 006: Secret Store Replacement](./adr-006-secret-store-replacement.md) -* [ADR 009: Evidence Module](./adr-009-evidence-module.md) -* [ADR 010: Modular AnteHandler](./adr-010-modular-antehandler.md) -* [ADR 019: Protocol Buffer State Encoding](./adr-019-protobuf-state-encoding.md) -* [ADR 020: Protocol Buffer Transaction Encoding](./adr-020-protobuf-transaction-encoding.md) -* [ADR 021: Protocol Buffer Query Encoding](./adr-021-protobuf-query-encoding.md) -* [ADR 023: Protocol Buffer Naming and Versioning](./adr-023-protobuf-naming.md) -* [ADR 029: Fee Grant Module](./adr-029-fee-grant-module.md) -* [ADR 030: Message Authorization Module](./adr-030-authz-module.md) -* [ADR 031: Protobuf Msg Services](./adr-031-msg-service.md) -* [ADR 055: ORM](./adr-055-orm.md) -* [ADR 058: Auto-Generated CLI](./adr-058-auto-generated-cli.md) +* [ADR 002: SDK Documentation Structure](adr-002-docs-structure.md) +* [ADR 004: Split Denomination Keys](adr-004-split-denomination-keys.md) +* [ADR 006: Secret Store Replacement](adr-006-secret-store-replacement.md) +* [ADR 009: Evidence Module](adr-009-evidence-module.md) +* [ADR 010: Modular AnteHandler](adr-010-modular-antehandler.md) +* [ADR 019: Protocol Buffer State Encoding](adr-019-protobuf-state-encoding.md) +* [ADR 020: Protocol Buffer Transaction Encoding](adr-020-protobuf-transaction-encoding.md) +* [ADR 021: Protocol Buffer Query Encoding](adr-021-protobuf-query-encoding.md) +* [ADR 023: Protocol Buffer Naming and Versioning](adr-023-protobuf-naming.md) +* [ADR 029: Fee Grant Module](adr-029-fee-grant-module.md) +* [ADR 030: Message Authorization Module](adr-030-authz-module.md) +* [ADR 031: Protobuf Msg Services](adr-031-msg-service.md) +* [ADR 055: ORM](adr-055-orm.md) +* [ADR 058: Auto-Generated CLI](adr-058-auto-generated-cli.md) +* [ADR 060: ABCI 1.0 (Phase I)](adr-060-abci-1.0.md) +* [ADR 061: Liquid Staking](adr-061-liquid-staking.md) ### Proposed -* [ADR 003: Dynamic Capability Store](./adr-003-dynamic-capability-store.md) -* [ADR 011: Generalize Genesis Accounts](./adr-011-generalize-genesis-accounts.md) -* [ADR 012: State Accessors](./adr-012-state-accessors.md) -* [ADR 013: Metrics](./adr-013-metrics.md) -* [ADR 016: Validator Consensus Key Rotation](./adr-016-validator-consensus-key-rotation.md) -* [ADR 017: Historical Header Module](./adr-017-historical-header-module.md) -* [ADR 018: Extendable Voting Periods](./adr-018-extendable-voting-period.md) -* [ADR 022: Custom baseapp panic handling](./adr-022-custom-panic-handling.md) -* [ADR 024: Coin Metadata](./adr-024-coin-metadata.md) -* [ADR 027: Deterministic Protobuf Serialization](./adr-027-deterministic-protobuf-serialization.md) -* [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) -* [ADR 032: Typed Events](./adr-032-typed-events.md) -* [ADR 033: Inter-module RPC](./adr-033-protobuf-inter-module-comm.md) -* [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) -* [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) -* [ADR 038: State Listening](./adr-038-state-listening.md) -* [ADR 039: Epoched Staking](./adr-039-epoched-staking.md) -* [ADR 040: Storage and SMT State Commitments](./adr-040-storage-and-smt-state-commitments.md) -* [ADR 046: Module Params](./adr-046-module-params.md) -* [ADR 057: App Wiring](./adr-057-app-wiring.md) -* [ADR 059: Test Scopes](./adr-059-test-scopes.md) -* [ADR 060: ABCI 1.0](adr-060-abci-1.0.md) +* [ADR 003: Dynamic Capability Store](adr-003-dynamic-capability-store.md) +* [ADR 011: Generalize Genesis Accounts](adr-011-generalize-genesis-accounts.md) +* [ADR 012: State Accessors](adr-012-state-accessors.md) +* [ADR 013: Metrics](adr-013-metrics.md) +* [ADR 016: Validator Consensus Key Rotation](adr-016-validator-consensus-key-rotation.md) +* [ADR 017: Historical Header Module](adr-017-historical-header-module.md) +* [ADR 018: Extendable Voting Periods](adr-018-extendable-voting-period.md) +* [ADR 022: Custom baseapp panic handling](adr-022-custom-panic-handling.md) +* [ADR 024: Coin Metadata](adr-024-coin-metadata.md) +* [ADR 027: Deterministic Protobuf Serialization](adr-027-deterministic-protobuf-serialization.md) +* [ADR 028: Public Key Addresses](adr-028-public-key-addresses.md) +* [ADR 032: Typed Events](adr-032-typed-events.md) +* [ADR 033: Inter-module RPC](adr-033-protobuf-inter-module-comm.md) +* [ADR 035: Rosetta API Support](adr-035-rosetta-api-support.md) +* [ADR 037: Governance Split Votes](adr-037-gov-split-vote.md) +* [ADR 038: State Listening](adr-038-state-listening.md) +* [ADR 039: Epoched Staking](adr-039-epoched-staking.md) +* [ADR 040: Storage and SMT State Commitments](adr-040-storage-and-smt-state-commitments.md) +* [ADR 046: Module Params](adr-046-module-params.md) +* [ADR 054: Semver Compatible SDK Modules](adr-054-semver-compatible-modules.md) +* [ADR 057: App Wiring](adr-057-app-wiring.md) +* [ADR 059: Test Scopes](adr-059-test-scopes.md) +* [ADR 062: Collections State Layer](adr-062-collections-state-layer.md) +* [ADR 063: Core Module API](adr-063-core-module-api.md) +* [ADR 065: Store V2](adr-065-store-v2.md) ### Draft -* [ADR 044: Guidelines for Updating Protobuf Definitions](./adr-044-protobuf-updates-guidelines.md) -* [ADR 047: Extend Upgrade Plan](./adr-047-extend-upgrade-plan.md) -* [ADR 053: Go Module Refactoring](./adr-053-go-module-refactoring.md) +* [ADR 044: Guidelines for Updating Protobuf Definitions](adr-044-protobuf-updates-guidelines.md) +* [ADR 047: Extend Upgrade Plan](adr-047-extend-upgrade-plan.md) +* [ADR 053: Go Module Refactoring](adr-053-go-module-refactoring.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/_category_.json b/versioned_docs/version-0.47/integrate/architecture/_category_.json index d138de900..87ceb9374 100644 --- a/versioned_docs/version-0.47/integrate/architecture/_category_.json +++ b/versioned_docs/version-0.47/integrate/architecture/_category_.json @@ -1,5 +1,5 @@ { "label": "ADRs", - "position": 10, + "position": 11, "link": null -} +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-007-specialization-groups.md b/versioned_docs/version-0.47/integrate/architecture/adr-007-specialization-groups.md index 58f78abf5..9a351dd1a 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-007-specialization-groups.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-007-specialization-groups.md @@ -174,4 +174,4 @@ type SpecializationGroup interface { ## References -* [dCERT ADR](./adr-008-dCERT-group.md) +* [dCERT ADR](adr-008-dCERT-group.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-008-dCERT-group.md b/versioned_docs/version-0.47/integrate/architecture/adr-008-dCERT-group.md index 2b2d2b826..2097bf1b9 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-008-dCERT-group.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-008-dCERT-group.md @@ -32,7 +32,7 @@ vulnerability being patched on the live network. ## Decision The dCERT group is proposed to include an implementation of a `SpecializationGroup` -as defined in [ADR 007](./adr-007-specialization-groups.md). This will include the +as defined in [ADR 007](adr-007-specialization-groups.md). This will include the implementation of: * continuous voting @@ -168,4 +168,4 @@ they should all be severely slashed. ## References - [Specialization Groups ADR](./adr-007-specialization-groups.md) + [Specialization Groups ADR](adr-007-specialization-groups.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-016-validator-consensus-key-rotation.md b/versioned_docs/version-0.47/integrate/architecture/adr-016-validator-consensus-key-rotation.md index 0510c2b9b..1d91a8de7 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-016-validator-consensus-key-rotation.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-016-validator-consensus-key-rotation.md @@ -85,12 +85,12 @@ Also, it should be noted that this ADR includes only the simplest form of consen ```go abci.ValidatorUpdate{ - PubKey: tmtypes.TM2PB.PubKey(OldConsPubKey), + PubKey: cmttypes.TM2PB.PubKey(OldConsPubKey), Power: 0, } abci.ValidatorUpdate{ - PubKey: tmtypes.TM2PB.PubKey(NewConsPubKey), + PubKey: cmttypes.TM2PB.PubKey(NewConsPubKey), Power: v.ConsensusPower(), } ``` diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-020-protobuf-transaction-encoding.md b/versioned_docs/version-0.47/integrate/architecture/adr-020-protobuf-transaction-encoding.md index 4c30bb9eb..344a7fef5 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-020-protobuf-transaction-encoding.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-020-protobuf-transaction-encoding.md @@ -23,7 +23,7 @@ Accepted ## Context This ADR is a continuation of the motivation, design, and context established in -[ADR 019](./adr-019-protobuf-state-encoding.md), namely, we aim to design the +[ADR 019](adr-019-protobuf-state-encoding.md), namely, we aim to design the Protocol Buffer migration path for the client-side of the Cosmos SDK. Specifically, the client-side migration path primarily includes tx generation and @@ -205,7 +205,7 @@ message SignDoc { In order to sign in the default mode, clients take the following steps: 1. Serialize `TxBody` and `AuthInfo` using any valid protobuf implementation. -2. Create a `SignDoc` and serialize it using [ADR 027](./adr-027-deterministic-protobuf-serialization.md). +2. Create a `SignDoc` and serialize it using [ADR 027](adr-027-deterministic-protobuf-serialization.md). 3. Sign the encoded `SignDoc` bytes. 4. Build a `TxRaw` and serialize it for broadcasting. @@ -221,7 +221,7 @@ Signature verifiers do: 3. For each required signer: * Pull account number and sequence from the state. * Obtain the public key either from state or `AuthInfo`'s `signer_infos`. - * Create a `SignDoc` and serialize it using [ADR 027](./adr-027-deterministic-protobuf-serialization.md). + * Create a `SignDoc` and serialize it using [ADR 027](adr-027-deterministic-protobuf-serialization.md). * Verify the signature at the same list position against the serialized `SignDoc`. #### `SIGN_MODE_LEGACY_AMINO` @@ -312,7 +312,7 @@ enforce this. Currently, the REST and CLI handlers encode and decode types and txs via Amino JSON encoding using a concrete Amino codec. Being that some of the types dealt with -in the client can be interfaces, similar to how we described in [ADR 019](./adr-019-protobuf-state-encoding.md), +in the client can be interfaces, similar to how we described in [ADR 019](adr-019-protobuf-state-encoding.md), the client logic will now need to take a codec interface that knows not only how to handle all the types, but also knows how to generate transactions, signatures, and messages. diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-021-protobuf-query-encoding.md b/versioned_docs/version-0.47/integrate/architecture/adr-021-protobuf-query-encoding.md index a90e807d5..76fd40feb 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-021-protobuf-query-encoding.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-021-protobuf-query-encoding.md @@ -11,11 +11,11 @@ Accepted ## Context This ADR is a continuation of the motivation, design, and context established in -[ADR 019](./adr-019-protobuf-state-encoding.md) and -[ADR 020](./adr-020-protobuf-transaction-encoding.md), namely, we aim to design the +[ADR 019](adr-019-protobuf-state-encoding.md) and +[ADR 020](adr-020-protobuf-transaction-encoding.md), namely, we aim to design the Protocol Buffer migration path for the client-side of the Cosmos SDK. -This ADR continues from [ADD 020](./adr-020-protobuf-transaction-encoding.md) +This ADR continues from [ADD 020](adr-020-protobuf-transaction-encoding.md) to specify the encoding of queries. ## Decision diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-022-custom-panic-handling.md b/versioned_docs/version-0.47/integrate/architecture/adr-022-custom-panic-handling.md index 6ed7b6246..2cdce59f4 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-022-custom-panic-handling.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-022-custom-panic-handling.md @@ -23,7 +23,7 @@ We propose middleware-solution, which could help developers implement the follow * call panic for specific error cases; It will also make `OutOfGas` case and `default` case one of the middlewares. -`Default` case wraps recovery object to an error and logs it ([example middleware implementation](#Recovery-middleware)). +`Default` case wraps recovery object to an error and logs it ([example middleware implementation](#recovery-middleware)). Our project has a sidecar service running alongside the blockchain node (smart contracts virtual machine). It is essential that node <-> sidecar connectivity stays stable for TXs processing. So when the communication breaks we need @@ -107,7 +107,7 @@ func newOutOfGasRecoveryMiddleware(gasWanted uint64, ctx sdk.Context, next recov err, ok := recoveryObj.(sdk.ErrorOutOfGas) if !ok { return nil } - return sdkerrors.Wrap( + return errorsmod.Wrap( sdkerrors.ErrOutOfGas, fmt.Sprintf( "out of gas in location: %v; gasWanted: %d, gasUsed: %d", err.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(), ), @@ -123,7 +123,7 @@ func newOutOfGasRecoveryMiddleware(gasWanted uint64, ctx sdk.Context, next recov ```go func newDefaultRecoveryMiddleware() recoveryMiddleware { handler := func(recoveryObj interface{}) error { - return sdkerrors.Wrap( + return errorsmod.Wrap( sdkerrors.ErrPanic, fmt.Sprintf("recovered: %v\nstack:\n%v", recoveryObj, string(debug.Stack())), ) } diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-024-coin-metadata.md b/versioned_docs/version-0.47/integrate/architecture/adr-024-coin-metadata.md index 3c55f80f0..71bedac5b 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-024-coin-metadata.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-024-coin-metadata.md @@ -65,6 +65,7 @@ As an example, the ATOM's metadata can be defined as follows: ```json { + "name": "atom", "description": "The native staking token of the Cosmos Hub.", "denom_units": [ { diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-027-deterministic-protobuf-serialization.md b/versioned_docs/version-0.47/integrate/architecture/adr-027-deterministic-protobuf-serialization.md index 66ce6e2b7..e19a45a73 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-027-deterministic-protobuf-serialization.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-027-deterministic-protobuf-serialization.md @@ -27,7 +27,7 @@ other cases as well. For signature verification in Cosmos SDK, the signer and verifier need to agree on the same serialization of a `SignDoc` as defined in -[ADR-020](./adr-020-protobuf-transaction-encoding.md) without transmitting the +[ADR-020](adr-020-protobuf-transaction-encoding.md) without transmitting the serialization. Currently, for block signatures we are using a workaround: we create a new [TxRaw](https://github.com/cosmos/cosmos-sdk/blob/9e85e81e0e8140067dd893421290c191529c148c/proto/cosmos/tx/v1beta1/tx.proto#L30) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-030-authz-module.md b/versioned_docs/version-0.47/integrate/architecture/adr-030-authz-module.md index 5aab72c5c..0454138d1 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-030-authz-module.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-030-authz-module.md @@ -25,7 +25,7 @@ The concrete use cases which motivated this module include: delegated stake * "sub-keys" functionality, as originally proposed in [\#4480](https://github.com/cosmos/cosmos-sdk/issues/4480) which is a term used to describe the functionality provided by this module together with -the `fee_grant` module from [ADR 029](./adr-029-fee-grant-module.md) and the [group module](https://github.com/cosmos/cosmos-sdk/tree/main/x/group). +the `fee_grant` module from [ADR 029](adr-029-fee-grant-module.md) and the [group module](https://github.com/cosmos/cosmos-sdk/tree/main/x/group). The "sub-keys" functionality roughly refers to the ability for one account to grant some subset of its capabilities to other accounts with possibly less robust, but easier to use security measures. For instance, a master account representing diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-031-msg-service.md b/versioned_docs/version-0.47/integrate/architecture/adr-031-msg-service.md index 861f4b3f3..b8e4005d2 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-031-msg-service.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-031-msg-service.md @@ -105,12 +105,12 @@ One consequence of this convention is that each `Msg` type can be the request pa ### Encoding -Encoding of transactions generated with `Msg` services do not differ from current Protobuf transaction encoding as defined in [ADR-020](./adr-020-protobuf-transaction-encoding.md). We are encoding `Msg` types (which are exactly `Msg` service methods' request parameters) as `Any` in `Tx`s which involves packing the +Encoding of transactions generated with `Msg` services do not differ from current Protobuf transaction encoding as defined in [ADR-020](adr-020-protobuf-transaction-encoding.md). We are encoding `Msg` types (which are exactly `Msg` service methods' request parameters) as `Any` in `Tx`s which involves packing the binary-encoded `Msg` with its type URL. ### Decoding -Since `Msg` types are packed into `Any`, decoding transactions messages are done by unpacking `Any`s into `Msg` types. For more information, please refer to [ADR-020](./adr-020-protobuf-transaction-encoding.md#transactions). +Since `Msg` types are packed into `Any`, decoding transactions messages are done by unpacking `Any`s into `Msg` types. For more information, please refer to [ADR-020](adr-020-protobuf-transaction-encoding.md#transactions). ### Routing @@ -122,7 +122,7 @@ For backward compatability, the old handlers are not removed yet. If BaseApp rec ### Module Configuration -In [ADR 021](./adr-021-protobuf-query-encoding.md), we introduced a method `RegisterQueryService` +In [ADR 021](adr-021-protobuf-query-encoding.md), we introduced a method `RegisterQueryService` to `AppModule` which allows for modules to register gRPC queriers. To register `Msg` services, we attempt a more extensible approach by converting `RegisterQueryService` @@ -198,5 +198,5 @@ Finally, closing a module to client API opens desirable OCAP patterns discussed * [Initial Github Issue \#7122](https://github.com/cosmos/cosmos-sdk/issues/7122) * [proto 3 Language Guide: Defining Services](https://developers.google.com/protocol-buffers/docs/proto3#services) * [Initial pre-`Any` `Msg` designs](https://docs.google.com/document/d/1eEgYgvgZqLE45vETjhwIw4VOqK-5hwQtZtjVbiXnIGc) -* [ADR 020](./adr-020-protobuf-transaction-encoding.md) -* [ADR 021](./adr-021-protobuf-query-encoding.md) +* [ADR 020](adr-020-protobuf-transaction-encoding.md) +* [ADR 021](adr-021-protobuf-query-encoding.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-032-typed-events.md b/versioned_docs/version-0.47/integrate/architecture/adr-032-typed-events.md index 1e769f450..c1dd0a73c 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-032-typed-events.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-032-typed-events.md @@ -109,7 +109,7 @@ func ParseTypedEvent(event abci.Event) (proto.Message, error) { Here, the `EmitTypedEvent` is a method on `EventManager` which takes typed event as input and apply json serialization on it. Then it maps the JSON key/value pairs to `event.Attributes` and emits it in form of `sdk.Event`. `Event.Type` will be the type URL of the proto message. -When we subscribe to emitted events on the tendermint websocket, they are emitted in the form of an `abci.Event`. `ParseTypedEvent` parses the event back to it's original proto message. +When we subscribe to emitted events on the CometBFT websocket, they are emitted in the form of an `abci.Event`. `ParseTypedEvent` parses the event back to it's original proto message. **Step-2**: Add proto definitions for typed events for msgs in each module: @@ -209,7 +209,7 @@ func SubmitProposalEventHandler(ev proto.Message) (err error) { // should be implemented somewhere in the Cosmos SDK. The Cosmos SDK can include an EventEmitters for tm.event='Tx' // and/or tm.event='NewBlock' (the new block events may contain typed events) func TxEmitter(ctx context.Context, cliCtx client.Context, ehs ...EventHandler) (err error) { - // Instantiate and start tendermint RPC client + // Instantiate and start CometBFT RPC client client, err := cliCtx.GetNode() if err != nil { return err @@ -260,8 +260,8 @@ func TxEmitter(ctx context.Context, cliCtx client.Context, ehs ...EventHandler) return group.Wait() } -// PublishChainTxEvents events using tmclient. Waits on context shutdown signals to exit. -func PublishChainTxEvents(ctx context.Context, client tmclient.EventsClient, bus pubsub.Bus, mb module.BasicManager) (err error) { +// PublishChainTxEvents events using cmtclient. Waits on context shutdown signals to exit. +func PublishChainTxEvents(ctx context.Context, client cmtclient.EventsClient, bus pubsub.Bus, mb module.BasicManager) (err error) { // Subscribe to transaction events txch, err := client.Subscribe(ctx, "txevents", "tm.event='Tx'", 100) if err != nil { @@ -285,7 +285,7 @@ func PublishChainTxEvents(ctx context.Context, client tmclient.EventsClient, bus break case ed := <-ch: switch evt := ed.Data.(type) { - case tmtypes.EventDataTx: + case cmttypes.EventDataTx: if !evt.Result.IsOK() { continue } diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-033-protobuf-inter-module-comm.md b/versioned_docs/version-0.47/integrate/architecture/adr-033-protobuf-inter-module-comm.md index ea634dac9..9c02a6684 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-033-protobuf-inter-module-comm.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-033-protobuf-inter-module-comm.md @@ -11,8 +11,8 @@ Proposed ## Abstract This ADR introduces a system for permissioned inter-module communication leveraging the protobuf `Query` and `Msg` -service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) and -[ADR 031](./adr-031-msg-service.md) which provides: +service definitions defined in [ADR 021](adr-021-protobuf-query-encoding.md) and +[ADR 031](adr-031-msg-service.md) which provides: * stable protobuf based module interfaces to potentially later replace the keeper paradigm * stronger inter-module object capabilities (OCAPs) guarantees @@ -20,7 +20,7 @@ service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) a ## Context -In the current Cosmos SDK documentation on the [Object-Capability Model](../core/10-ocap.md), it is stated that: +In the current Cosmos SDK documentation on the [Object-Capability Model](../../develop/advanced-concepts/10-ocap.md), it is stated that: > We assume that a thriving ecosystem of Cosmos SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. @@ -48,7 +48,7 @@ just a simple string. So the `x/upgrade` module could mint tokens for the `x/sta ## Decision -Based on [ADR-021](./adr-021-protobuf-query-encoding.md) and [ADR-031](./adr-031-msg-service.md), we introduce the +Based on [ADR-021](adr-021-protobuf-query-encoding.md) and [ADR-031](adr-031-msg-service.md), we introduce the Inter-Module Communication framework for secure module authorization and OCAPs. When implemented, this could also serve as an alternative to the existing paradigm of passing keepers between modules. The approach outlined here-in is intended to form the basis of a Cosmos SDK v1.0 that provides the necessary @@ -60,8 +60,8 @@ addressed as amendments to this ADR. ### New "Keeper" Paradigm -In [ADR 021](./adr-021-protobuf-query-encoding.md), a mechanism for using protobuf service definitions to define queriers -was introduced and in [ADR 31](./adr-031-msg-service.md), a mechanism for using protobuf service to define `Msg`s was added. +In [ADR 021](adr-021-protobuf-query-encoding.md), a mechanism for using protobuf service definitions to define queriers +was introduced and in [ADR 31](adr-031-msg-service.md), a mechanism for using protobuf service to define `Msg`s was added. Protobuf service definitions generate two golang interfaces representing the client and server sides of a service plus some helper code. Here is a minimal example for the bank `cosmos.bank.Msg/Send` message type: @@ -77,7 +77,7 @@ type MsgServer interface { } ``` -[ADR 021](./adr-021-protobuf-query-encoding.md) and [ADR 31](./adr-031-msg-service.md) specifies how modules can implement the generated `QueryServer` +[ADR 021](adr-021-protobuf-query-encoding.md) and [ADR 31](adr-031-msg-service.md) specifies how modules can implement the generated `QueryServer` and `MsgServer` interfaces as replacements for the legacy queriers and `Msg` handlers respectively. In this ADR we explain how modules can make queries and send `Msg`s to other modules using the generated `QueryClient` @@ -161,7 +161,7 @@ denom prefix being restricted to certain modules (as discussed in ### `ModuleKey`s and `ModuleID`s A `ModuleKey` can be thought of as a "private key" for a module account and a `ModuleID` can be thought of as the -corresponding "public key". From the [ADR 028](./adr-028-public-key-addresses.md), modules can have both a root module account and any number of sub-accounts +corresponding "public key". From the [ADR 028](adr-028-public-key-addresses.md), modules can have both a root module account and any number of sub-accounts or derived accounts that can be used for different pools (ex. staking pools) or managed accounts (ex. group accounts). We can also think of module sub-accounts as similar to derived keys - there is a root key and then some derivation path. `ModuleID` is a simple struct which contains the module name and optional "derivation" path, @@ -248,7 +248,7 @@ func (key RootModuleKey) Invoke(ctx context.Context, method string, args, reply ### `AppModule` Wiring and Requirements -In [ADR 031](./adr-031-msg-service.md), the `AppModule.RegisterService(Configurator)` method was introduced. To support +In [ADR 031](adr-031-msg-service.md), the `AppModule.RegisterService(Configurator)` method was introduced. To support inter-module communication, we extend the `Configurator` interface to pass in the `ModuleKey` and to allow modules to specify their dependencies on other modules using `RequireServer()`: @@ -393,8 +393,8 @@ replacing `Keeper` interfaces altogether. ## References -* [ADR 021](./adr-021-protobuf-query-encoding.md) -* [ADR 031](./adr-031-msg-service.md) -* [ADR 028](./adr-028-public-key-addresses.md) +* [ADR 021](adr-021-protobuf-query-encoding.md) +* [ADR 031](adr-031-msg-service.md) +* [ADR 028](adr-028-public-key-addresses.md) * [ADR 030 draft](https://github.com/cosmos/cosmos-sdk/pull/7105) * [Object-Capability Model](https://docs.network.com/main/core/ocap) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-038-state-listening.md b/versioned_docs/version-0.47/integrate/architecture/adr-038-state-listening.md index 74f92d2f6..2b6a220b4 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-038-state-listening.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-038-state-listening.md @@ -3,10 +3,11 @@ ## Changelog * 11/23/2020: Initial draft +* 10/06/2022: Introduce plugin system based on hashicorp/go-plugin * 10/14/2022: - * Add `ListenCommit`, flatten the state writes in a block to a single batch. - * Remove listeners from cache stores, should only listen to `rootmulti.Store`. - * Remove `HaltAppOnDeliveryError()`, the errors are propogated by default, the implementations should return nil if don't want to propogate errors. + * Add `ListenCommit`, flatten the state writes in a block to a single batch. + * Remove listeners from cache stores, should only listen to `rootmulti.Store`. + * Remove `HaltAppOnDeliveryError()`, the errors are propagated by default, the implementations should return nil if don't want to propogate errors. ## Status @@ -19,7 +20,7 @@ This ADR defines a set of changes to enable listening to state changes of indivi ## Context -Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/02-messages-and-queries.md#queries) which proceed either through Tendermint and the ABCI, or through the gRPC server. In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. @@ -28,93 +29,30 @@ In addition to these request/response queries, it would be beneficial to have a We will modify the `CommitMultiStore` interface and its concrete (`rootmulti`) implementations and introduce a new `listenkv.Store` to allow listening to state changes in underlying KVStores. We don't need to listen to cache stores, because we can't be sure that the writes will be committed eventually, and the writes are duplicated in `rootmulti.Store` eventually, so we should only listen to `rootmulti.Store`. We will introduce a plugin system for configuring and running streaming services that write these state changes and their surrounding ABCI message context to different destinations. -### Listening interface +### Listening -In a new file, `store/types/listening.go`, we will create a `WriteListener` interface for streaming out state changes from a KVStore. +In a new file, `store/types/listening.go`, we will create a `MemoryListener` struct for streaming out protobuf encoded KV pairs state changes from a KVStore. +The `MemoryListener` will be used internally by the concrete `rootmulti` implementation to collect state changes from KVStores. ```go -// WriteListener interface for streaming data out from a listenkv.Store -type WriteListener interface { - // if value is nil then it was deleted - // storeKey indicates the source KVStore, to facilitate using the same WriteListener across separate KVStores - // delete bool indicates if it was a delete; true: delete, false: set - OnWrite(storeKey StoreKey, key []byte, value []byte, delete bool) error -} -``` - -### Listener type - -We will create two concrete implementations of the `WriteListener` interface in `store/types/listening.go`, that writes out protobuf -encoded KV pairs to an underlying `io.Writer`, and simply accumulate them in memory. - -This will include defining a simple protobuf type for the KV pairs. In addition to the key and value fields this message -will include the StoreKey for the originating KVStore so that we can write out from separate KVStores to the same stream/file -and determine the source of each KV pair. - -```protobuf -message StoreKVPair { - optional string store_key = 1; // the store key for the KVStore this pair originates from - required bool set = 2; // true indicates a set operation, false indicates a delete operation - required bytes key = 3; - required bytes value = 4; -} -``` - -```go -// StoreKVPairWriteListener is used to configure listening to a KVStore by writing out length-prefixed -// protobuf encoded StoreKVPairs to an underlying io.Writer -type StoreKVPairWriteListener struct { - writer io.Writer - marshaller codec.BinaryCodec -} - -// NewStoreKVPairWriteListener wraps creates a StoreKVPairWriteListener with a provdied io.Writer and codec.BinaryCodec -func NewStoreKVPairWriteListener(w io.Writer, m codec.BinaryCodec) *StoreKVPairWriteListener { - return &StoreKVPairWriteListener{ - writer: w, - marshaller: m, - } -} - -// OnWrite satisfies the WriteListener interface by writing length-prefixed protobuf encoded StoreKVPairs -func (wl *StoreKVPairWriteListener) OnWrite(storeKey types.StoreKey, key []byte, value []byte, delete bool) error error { - kvPair := new(types.StoreKVPair) - kvPair.StoreKey = storeKey.Name() - kvPair.Delete = Delete - kvPair.Key = key - kvPair.Value = value - by, err := wl.marshaller.MarshalBinaryLengthPrefixed(kvPair) - if err != nil { - return err - } - if _, err := wl.writer.Write(by); err != nil { - return err - } - return nil -} -``` - -```golang // MemoryListener listens to the state writes and accumulate the records in memory. type MemoryListener struct { - key StoreKey stateCache []StoreKVPair } // NewMemoryListener creates a listener that accumulate the state writes in memory. -func NewMemoryListener(key StoreKey) *MemoryListener { - return &MemoryListener{key: key} +func NewMemoryListener() *MemoryListener { + return &MemoryListener{} } -// OnWrite implements WriteListener interface -func (fl *MemoryListener) OnWrite(storeKey StoreKey, key []byte, value []byte, delete bool) error { +// OnWrite writes state change events to the internal cache +func (fl *MemoryListener) OnWrite(storeKey StoreKey, key []byte, value []byte, delete bool) { fl.stateCache = append(fl.stateCache, StoreKVPair{ StoreKey: storeKey.Name(), Delete: delete, Key: key, Value: value, }) - return nil } // PopStateCache returns the current state caches and set to nil @@ -123,32 +61,39 @@ func (fl *MemoryListener) PopStateCache() []StoreKVPair { fl.stateCache = nil return res } +``` + +We will also define a protobuf type for the KV pairs. In addition to the key and value fields this message +will include the StoreKey for the originating KVStore so that we can collect information from separate KVStores and determine the source of each KV pair. -// StoreKey returns the storeKey it listens to -func (fl *MemoryListener) StoreKey() StoreKey { - return fl.key +```protobuf +message StoreKVPair { + optional string store_key = 1; // the store key for the KVStore this pair originates from + required bool set = 2; // true indicates a set operation, false indicates a delete operation + required bytes key = 3; + required bytes value = 4; } ``` ### ListenKVStore -We will create a new `Store` type `listenkv.Store` that the `MultiStore` wraps around a `KVStore` to enable state listening. -We can configure the `Store` with a set of `WriteListener`s which stream the output to specific destinations. +We will create a new `Store` type `listenkv.Store` that the `rootmulti` store will use to wrap a `KVStore` to enable state listening. +We will configure the `Store` with a `MemoryListener` which will collect state changes for output to specific destinations. ```go // Store implements the KVStore interface with listening enabled. -// Operations are traced on each core KVStore call and written to any of the +// Operations are traced on each advanced-concepts KVStore call and written to any of the // underlying listeners with the proper key and operation permissions type Store struct { parent types.KVStore - listeners []types.WriteListener + listener *types.MemoryListener parentStoreKey types.StoreKey } // NewStore returns a reference to a new traceKVStore given a parent // KVStore implementation and a buffered writer. -func NewStore(parent types.KVStore, psk types.StoreKey, listeners []types.WriteListener) *Store { - return &Store{parent: parent, listeners: listeners, parentStoreKey: psk} +func NewStore(parent types.KVStore, psk types.StoreKey, listener *types.MemoryListener) *Store { + return &Store{parent: parent, listener: listener, parentStoreKey: psk} } // Set implements the KVStore interface. It traces a write operation and @@ -156,47 +101,38 @@ func NewStore(parent types.KVStore, psk types.StoreKey, listeners []types.WriteL func (s *Store) Set(key []byte, value []byte) { types.AssertValidKey(key) s.parent.Set(key, value) - s.onWrite(false, key, value) + s.listener.OnWrite(s.parentStoreKey, key, value, false) } // Delete implements the KVStore interface. It traces a write operation and // delegates the Delete call to the parent KVStore. func (s *Store) Delete(key []byte) { s.parent.Delete(key) - s.onWrite(true, key, nil) -} - -// onWrite writes a KVStore operation to all the WriteListeners -func (s *Store) onWrite(delete bool, key, value []byte) { - for _, l := range s.listeners { - if err := l.OnWrite(s.parentStoreKey, key, value, delete); err != nil { - // log error - } - } + s.listener.OnWrite(s.parentStoreKey, key, nil, true) } ``` ### MultiStore interface updates -We will update the `CommitMultiStore` interface to allow us to wrap a set of listeners around a specific `KVStore`. +We will update the `CommitMultiStore` interface to allow us to wrap a `Memorylistener` to a specific `KVStore`. +Note that the `MemoryListener` will be attached internally by the concrete `rootmulti` implementation. ```go type CommitMultiStore interface { ... - // ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey - ListeningEnabled(key StoreKey) bool + // AddListeners adds a listener for the KVStore belonging to the provided StoreKey + AddListeners(keys []StoreKey) - // AddListeners adds WriteListeners for the KVStore belonging to the provided StoreKey - // It appends the listeners to a current set, if one already exists - AddListeners(key StoreKey, listeners []WriteListener) + // PopStateCache returns the accumulated state change messages from MemoryListener + PopStateCache() []StoreKVPair } ``` + ### MultiStore implementation updates -We will modify all of the `CommitMultiStore` implementations to satisfy these new interfaces, and adjust the `rootmulti` `GetKVStore` method -to wrap the returned `KVStore` with a `listenkv.Store` if listening is turned on for that `Store`. +We will adjust the `rootmulti` `GetKVStore` method to wrap the returned `KVStore` with a `listenkv.Store` if listening is turned on for that `Store`. ```go func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { @@ -206,339 +142,656 @@ func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { store = tracekv.NewStore(store, rs.traceWriter, rs.traceContext) } if rs.ListeningEnabled(key) { - store = listenkv.NewStore(key, store, rs.listeners[key]) + store = listenkv.NewStore(store, key, rs.listeners[key]) } return store } ``` -We will also adjust the `rootmulti` `CacheMultiStore` method to wrap the stores with `listenkv.Store` to enable listening when the cache layer writes. +We will implement `AddListeners` to manage KVStore listeners internally and implement `PopStateCache` +for a means of retrieving the current state. ```go -func (rs *Store) CacheMultiStore() types.CacheMultiStore { - stores := make(map[types.StoreKey]types.CacheWrapper) - for k, v := range rs.stores { - store := v.(types.KVStore) - // Wire the listenkv.Store to allow listeners to observe the writes from the cache store, - // set same listeners on cache store will observe duplicated writes. - if rs.ListeningEnabled(k) { - store = listenkv.NewStore(store, k, rs.listeners[k]) - } - stores[k] = store +// AddListeners adds state change listener for a specific KVStore +func (rs *Store) AddListeners(keys []types.StoreKey) { + listener := types.NewMemoryListener() + for i := range keys { + rs.listeners[keys[i]] = listener } - return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.getTracingContext()) } ``` -### Exposing the data +```go +func (rs *Store) PopStateCache() []types.StoreKVPair { + var cache []types.StoreKVPair + for _, ls := range rs.listeners { + cache = append(cache, ls.PopStateCache()...) + } + sort.SliceStable(cache, func(i, j int) bool { + return cache[i].StoreKey < cache[j].StoreKey + }) + return cache +} +``` + +We will also adjust the `rootmulti` `CacheMultiStore` and `CacheMultiStoreWithVersion` methods to enable listening in +the cache layer. + +```go +func (rs *Store) CacheMultiStore() types.CacheMultiStore { + stores := make(map[types.StoreKey]types.CacheWrapper) + for k, v := range rs.stores { + store := v.(types.KVStore) + // Wire the listenkv.Store to allow listeners to observe the writes from the cache store, + // set same listeners on cache store will observe duplicated writes. + if rs.ListeningEnabled(k) { + store = listenkv.NewStore(store, k, rs.listeners[k]) + } + stores[k] = store + } + return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.getTracingContext()) +} +``` -#### Streaming service +```go +func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { + // ... -We will introduce a new `StreamingService` interface for exposing `WriteListener` data streams to external consumers. -In addition to streaming state changes as `StoreKVPair`s, the interface satisfies an `ABCIListener` interface that plugs -into the BaseApp and relays ABCI requests and responses so that the service can observe those block metadatas as well. + // Wire the listenkv.Store to allow listeners to observe the writes from the cache store, + // set same listeners on cache store will observe duplicated writes. + if rs.ListeningEnabled(key) { + cacheStore = listenkv.NewStore(cacheStore, key, rs.listeners[key]) + } -The `WriteListener`s of `StreamingService` listens to the `rootmulti.Store`, which is only written into at commit event by the cache store of `deliverState`. + cachedStores[key] = cacheStore + } + + return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.getTracingContext()), nil +} +``` + +### Exposing the data + +#### Streaming Service + +We will introduce a new `ABCIListener` interface that plugs into the BaseApp and relays ABCI requests and responses +so that the service can group the state changes with the ABCI requests. ```go -// ABCIListener interface used to hook into the ABCI message processing of the BaseApp +// baseapp/streaming.go + +// ABCIListener is the interface that we're exposing as a streaming service. type ABCIListener interface { // ListenBeginBlock updates the streaming service with the latest BeginBlock messages - ListenBeginBlock(ctx types.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error + ListenBeginBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error // ListenEndBlock updates the steaming service with the latest EndBlock messages ListenEndBlock(ctx types.Context, req abci.RequestEndBlock, res abci.ResponseEndBlock) error // ListenDeliverTx updates the steaming service with the latest DeliverTx messages - ListenDeliverTx(ctx types.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) error - // ListenCommit updates the steaming service with the latest Commit message, - // All the state writes of current block should have notified before this message. - ListenCommit(ctx types.Context, res abci.ResponseCommit) error -} - -// StreamingService interface for registering WriteListeners with the BaseApp and updating the service with the ABCI messages using the hooks -type StreamingService interface { - // Stream is the streaming service loop, awaits kv pairs and writes them to a destination stream or file - Stream(wg *sync.WaitGroup) error - // Listeners returns the streaming service's listeners for the BaseApp to register - Listeners() map[types.StoreKey][]store.WriteListener - // ABCIListener interface for hooking into the ABCI messages from inside the BaseApp - ABCIListener - // Closer interface - io.Closer + ListenDeliverTx(ctx context.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) error + // ListenCommit updates the steaming service with the latest Commit messages and state changes + ListenCommit(ctx context.Context, res abci.ResponseCommit, changeSet []*store.StoreKVPair) error } ``` -#### BaseApp registration +#### BaseApp Registration We will add a new method to the `BaseApp` to enable the registration of `StreamingService`s: + ```go + // SetStreamingService is used to set a streaming service into the BaseApp hooks and load the listeners into the multistore +func (app *BaseApp) SetStreamingService(s ABCIListener) { + // register the StreamingService within the BaseApp + // BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context + app.abciListeners = append(app.abciListeners, s) +} +``` + +We will add two new fields to the `BaseApp` struct: + ```go -// SetStreamingService is used to set a streaming service into the BaseApp hooks and load the listeners into the multistore -func (app *BaseApp) SetStreamingService(s StreamingService) { - // add the listeners for each StoreKey - for key, lis := range s.Listeners() { - app.cms.AddListeners(key, lis) - } - // register the StreamingService within the BaseApp - // BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context - app.abciListeners = append(app.abciListeners, s) +type BaseApp struct { + + ... + + // abciListenersAsync for determining if abciListeners will run asynchronously. + // When abciListenersAsync=false and stopNodeOnABCIListenerErr=false listeners will run synchronized but will not stop the node. + // When abciListenersAsync=true stopNodeOnABCIListenerErr will be ignored. + abciListenersAsync bool + + // stopNodeOnABCIListenerErr halts the node when ABCI streaming service listening results in an error. + // stopNodeOnABCIListenerErr=true must be paired with abciListenersAsync=false. + stopNodeOnABCIListenerErr bool } ``` -We will also modify the `BeginBlock`, `EndBlock`, and `DeliverTx` methods to pass ABCI requests and responses to any streaming service hooks registered -with the `BaseApp`. +#### ABCI Event Hooks + +We will modify the `BeginBlock`, `EndBlock`, `DeliverTx` and `Commit` methods to pass ABCI requests and responses +to any streaming service hooks registered with the `BaseApp`. ```go func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { - ... + ... - defer func() { - // call the hooks with the BeginBlock messages - for _, streamingListener := range app.abciListeners { - if err := streamingListener.ListenBeginBlock(app.deliverState.ctx, req, res); err != nil { - panic(sdkerrors.Wrapf(err, "BeginBlock listening hook failed, height: %d", req.Header.Height)) - } - } - }() + // call the streaming service hook with the BeginBlock messages + for _, abciListener := range app.abciListeners { + ctx := app.deliverState.ctx + blockHeight := ctx.BlockHeight() + if app.abciListenersAsync { + go func(req abci.RequestBeginBlock, res abci.ResponseBeginBlock) { + if err := app.abciListener.ListenBeginBlock(ctx, req, res); err != nil { + app.logger.Error("BeginBlock listening hook failed", "height", blockHeight, "err", err) + } + }(req, res) + } else { + if err := app.abciListener.ListenBeginBlock(ctx, req, res); err != nil { + app.logger.Error("BeginBlock listening hook failed", "height", blockHeight, "err", err) + if app.stopNodeOnABCIListenerErr { + os.Exit(1) + } + } + } + } - return res + return res } ``` ```go func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { - ... + ... - defer func() { - // Call the streaming service hooks with the EndBlock messages - for _, streamingListener := range app.abciListeners { - if err := streamingListener.ListenEndBlock(app.deliverState.ctx, req, res); err != nil { - panic(sdkerrors.Wrapf(err, "EndBlock listening hook failed, height: %d", req.Height)) - } - } - }() + // call the streaming service hook with the EndBlock messages + for _, abciListener := range app.abciListeners { + ctx := app.deliverState.ctx + blockHeight := ctx.BlockHeight() + if app.abciListenersAsync { + go func(req abci.RequestEndBlock, res abci.ResponseEndBlock) { + if err := app.abciListener.ListenEndBlock(blockHeight, req, res); err != nil { + app.logger.Error("EndBlock listening hook failed", "height", blockHeight, "err", err) + } + }(req, res) + } else { + if err := app.abciListener.ListenEndBlock(blockHeight, req, res); err != nil { + app.logger.Error("EndBlock listening hook failed", "height", blockHeight, "err", err) + if app.stopNodeOnABCIListenerErr { + os.Exit(1) + } + } + } + } - return res + return res } ``` ```go -func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) { - - defer func() { - // call the hooks with the DeliverTx messages - for _, streamingListener := range app.abciListeners { - if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, res); err != nil { - panic(sdkerrors.Wrap(err, "DeliverTx listening hook failed")) - } - } - }() +func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { + + var abciRes abci.ResponseDeliverTx + defer func() { + // call the streaming service hook with the EndBlock messages + for _, abciListener := range app.abciListeners { + ctx := app.deliverState.ctx + blockHeight := ctx.BlockHeight() + if app.abciListenersAsync { + go func(req abci.RequestDeliverTx, res abci.ResponseDeliverTx) { + if err := app.abciListener.ListenDeliverTx(blockHeight, req, res); err != nil { + app.logger.Error("DeliverTx listening hook failed", "height", blockHeight, "err", err) + } + }(req, abciRes) + } else { + if err := app.abciListener.ListenDeliverTx(blockHeight, req, res); err != nil { + app.logger.Error("DeliverTx listening hook failed", "height", blockHeight, "err", err) + if app.stopNodeOnABCIListenerErr { + os.Exit(1) + } + } + } + } + }() - ... + ... - return res + return abciRes } ``` -```golang +```go func (app *BaseApp) Commit() abci.ResponseCommit { - header := app.deliverState.ctx.BlockHeader() - retainHeight := app.GetBlockRetentionHeight(header.Height) - - // Write the DeliverTx state into branched storage and commit the MultiStore. - // The write to the DeliverTx state writes all state transitions to the root - // MultiStore (app.cms) so when Commit() is called is persists those values. - app.deliverState.ms.Write() - commitID := app.cms.Commit() - - res := abci.ResponseCommit{ - Data: commitID.Hash, - RetainHeight: retainHeight, - } - // call the hooks with the Commit message - for _, streamingListener := range app.abciListeners { - if err := streamingListener.ListenCommit(app.deliverState.ctx, res); err != nil { - panic(sdkerrors.Wrapf(err, "Commit listening hook failed, height: %d", header.Height)) - } - } + ... + + res := abci.ResponseCommit{ + Data: commitID.Hash, + RetainHeight: retainHeight, + } + + // call the streaming service hook with the Commit messages + for _, abciListener := range app.abciListeners { + ctx := app.deliverState.ctx + blockHeight := ctx.BlockHeight() + changeSet := app.cms.PopStateCache() + if app.abciListenersAsync { + go func(res abci.ResponseCommit, changeSet []store.StoreKVPair) { + if err := app.abciListener.ListenCommit(ctx, res, changeSet); err != nil { + app.logger.Error("ListenCommit listening hook failed", "height", blockHeight, "err", err) + } + }(res, changeSet) + } else { + if err := app.abciListener.ListenCommit(ctx, res, changeSet); err != nil { + app.logger.Error("ListenCommit listening hook failed", "height", blockHeight, "err", err) + if app.stopNodeOnABCIListenerErr { + os.Exit(1) + } + } + } + } + + ... - app.logger.Info("commit synced", "commit", fmt.Sprintf("%X", commitID)) - ... + return res } ``` -#### Error Handling And Async Consumers +#### Go Plugin System -`ABCIListener`s are called synchronously inside the consensus state machine, the returned error causes panic which in turn halt the consensus state machine. The implementer should be careful not to break consensus unexpectedly or slow down it too much. +We propose a plugin architecture to load and run `Streaming` plugins and other types of implementations. We will introduce a plugin +system over gRPC that is used to load and run Cosmos-SDK plugins. The plugin system uses [hashicorp/go-plugin](https://github.com/hashicorp/go-plugin). +Each plugin must have a struct that implements the `plugin.Plugin` interface and an `Impl` interface for processing messages over gRPC. +Each plugin must also have a message protocol defined for the gRPC service: -For some async use cases, one can spawn a go-routine internanlly to avoid slow down consensus state machine, and handle the errors internally and always returns `nil` to avoid halting consensus state machine on error. +```go +// streaming/plugins/abci/{plugin_version}/interface.go + +// Handshake is a common handshake that is shared by streaming and host. +// This prevents users from executing bad plugins or executing a plugin +// directory. It is a UX feature, not a security feature. +var Handshake = plugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ABCI_LISTENER_PLUGIN", + MagicCookieValue: "ef78114d-7bdf-411c-868f-347c99a78345", +} -Furthermore, for most of the cases, we only need to use the builtin file streamer to listen to state changes directly inside cosmos-sdk, the other consumers should subscribe to the file streamer output externally. +// ListenerPlugin is the base struc for all kinds of go-plugin implementations +// It will be included in interfaces of different Plugins +type ABCIListenerPlugin struct { + // GRPCPlugin must still implement the Plugin interface + plugin.Plugin + // Concrete implementation, written in Go. This is only used for plugins + // that are written in Go. + Impl baseapp.ABCIListener +} + +func (p *ListenerGRPCPlugin) GRPCServer(_ *plugin.GRPCBroker, s *grpc.Server) error { + RegisterABCIListenerServiceServer(s, &GRPCServer{Impl: p.Impl}) + return nil +} -#### File Streamer +func (p *ListenerGRPCPlugin) GRPCClient( + _ context.Context, + _ *plugin.GRPCBroker, + c *grpc.ClientConn, +) (interface{}, error) { + return &GRPCClient{client: NewABCIListenerServiceClient(c)}, nil +} +``` + +The `plugin.Plugin` interface has two methods `Client` and `Server`. For our GRPC service these are `GRPCClient` and `GRPCServer` +The `Impl` field holds the concrete implementation of our `baseapp.ABCIListener` interface written in Go. +Note: this is only used for plugin implementations written in Go. + +The advantage of having such a plugin system is that within each plugin authors can define the message protocol in a way that fits their use case. +For example, when state change listening is desired, the `ABCIListener` message protocol can be defined as below (*for illustrative purposes only*). +When state change listening is not desired than `ListenCommit` can be omitted from the protocol. + +```protobuf +syntax = "proto3"; -We provide a minimal filesystem based implementation inside cosmos-sdk, and provides options to write output files reliably, the output files can be further consumed by external consumers, so most of the state listeners actually don't need to live inside the sdk and node, which improves the node robustness and simplify sdk internals. +... -The file streamer can be wired in app like this: -```golang -exposeStoreKeys := ... // decide the key list to listen -service, err := file.NewStreamingService(streamingDir, "", exposeStoreKeys, appCodec, logger) -bApp.SetStreamingService(service) +message Empty {} + +message ListenBeginBlockRequest { + RequestBeginBlock req = 1; + ResponseBeginBlock res = 2; +} +message ListenEndBlockRequest { + RequestEndBlock req = 1; + ResponseEndBlock res = 2; +} +message ListenDeliverTxRequest { + int64 block_height = 1; + RequestDeliverTx req = 2; + ResponseDeliverTx res = 3; +} +message ListenCommitRequest { + int64 block_height = 1; + ResponseCommit res = 2; + repeated StoreKVPair changeSet = 3; +} + +// plugin that listens to state changes +service ABCIListenerService { + rpc ListenBeginBlock(ListenBeginBlockRequest) returns (Empty); + rpc ListenEndBlock(ListenEndBlockRequest) returns (Empty); + rpc ListenDeliverTx(ListenDeliverTxRequest) returns (Empty); + rpc ListenCommit(ListenCommitRequest) returns (Empty); +} ``` -#### Plugin system +```protobuf +... +// plugin that doesn't listen to state changes +service ABCIListenerService { + rpc ListenBeginBlock(ListenBeginBlockRequest) returns (Empty); + rpc ListenEndBlock(ListenEndBlockRequest) returns (Empty); + rpc ListenDeliverTx(ListenDeliverTxRequest) returns (Empty); + rpc ListenCommit(ListenCommitRequest) returns (Empty); +} +``` -We propose a plugin architecture to load and run `StreamingService` implementations. We will introduce a plugin -loading/preloading system that is used to load, initialize, inject, run, and stop Cosmos-SDK plugins. Each plugin -must implement the following interface: +Implementing the service above: ```go -// Plugin is the base interface for all kinds of cosmos-sdk plugins -// It will be included in interfaces of different Plugins -type Plugin interface { - // Name should return unique name of the plugin - Name() string +// streaming/plugins/abci/{plugin_version}/grpc.go + +var ( + _ baseapp.ABCIListener = (*GRPCClient)(nil) +) + +// GRPCClient is an implementation of the ABCIListener and ABCIListenerPlugin interfaces that talks over RPC. +type GRPCClient struct { + client ABCIListenerServiceClient +} + +func (m *GRPCClient) ListenBeginBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error { + _, err := m.client.ListenBeginBlock(ctx, &ListenBeginBlockRequest{Req: req, Res: res}) + return err +} + +func (m *GRPCClient) ListenEndBlock(goCtx context.Context, req abci.RequestEndBlock, res abci.ResponseEndBlock) error { + _, err := m.client.ListenEndBlock(ctx, &ListenEndBlockRequest{Req: req, Res: res}) + return err +} + +func (m *GRPCClient) ListenDeliverTx(goCtx context.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) error { + ctx := sdk.UnwrapSDKContext(goCtx) + _, err := m.client.ListenDeliverTx(ctx, &ListenDeliverTxRequest{BlockHeight: ctx.BlockHeight(), Req: req, Res: res}) + return err +} + +func (m *GRPCClient) ListenCommit(goCtx context.Context, res abci.ResponseCommit, changeSet []store.StoreKVPair) error { + ctx := sdk.UnwrapSDKContext(goCtx) + _, err := m.client.ListenCommit(ctx, &ListenCommitRequest{BlockHeight: ctx.BlockHeight(), Res: res, ChangeSet: changeSet}) + return err +} + +// GRPCServer is the gRPC server that GRPCClient talks to. +type GRPCServer struct { + // This is the real implementation + Impl baseapp.ABCIListener +} + +func (m *GRPCServer) ListenBeginBlock(ctx context.Context, req *ListenBeginBlockRequest) (*Empty, error) { + return &Empty{}, m.Impl.ListenBeginBlock(ctx, req.Req, req.Res) +} + +func (m *GRPCServer) ListenEndBlock(ctx context.Context, req *ListenEndBlockRequest) (*Empty, error) { + return &Empty{}, m.Impl.ListenEndBlock(ctx, req.Req, req.Res) +} + +func (m *GRPCServer) ListenDeliverTx(ctx context.Context, req *ListenDeliverTxRequest) (*Empty, error) { + return &Empty{}, m.Impl.ListenDeliverTx(ctx, req.Req, req.Res) +} + +func (m *GRPCServer) ListenCommit(ctx context.Context, req *ListenCommitRequest) (*Empty, error) { + return &Empty{}, m.Impl.ListenCommit(ctx, req.Res, req.ChangeSet) +} + +``` + +And the pre-compiled Go plugin `Impl`(*this is only used for plugins that are written in Go*): + +```go +// streaming/plugins/abci/{plugin_version}/impl/plugin.go + +// Plugins are pre-compiled and loaded by the plugin system - // Version returns current version of the plugin - Version() string +// ABCIListener is the implementation of the baseapp.ABCIListener interface +type ABCIListener struct{} + +func (m *ABCIListenerPlugin) ListenBeginBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error { + // send data to external system +} - // Init is called once when the Plugin is being loaded - // The plugin is passed the AppOptions for configuration - // A plugin will not necessarily have a functional Init - Init(env serverTypes.AppOptions) error +func (m *ABCIListenerPlugin) ListenEndBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error { + // send data to external system +} + +func (m *ABCIListenerPlugin) ListenDeliverTxBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error { + // send data to external system +} - // Closer interface for shutting down the plugin process - io.Closer +func (m *ABCIListenerPlugin) ListenCommit(ctx context.Context, res abci.ResponseCommit, changeSet []store.StoreKVPair) error { + // send data to external system +} + +func main() { + plugin.Serve(&plugin.ServeConfig{ + HandshakeConfig: grpc_abci_v1.Handshake, + Plugins: map[string]plugin.Plugin{ + "grpc_plugin_v1": &grpc_abci_v1.ABCIListenerGRPCPlugin{Impl: &ABCIListenerPlugin{}}, + }, + + // A non-nil value here enables gRPC serving for this streaming... + GRPCServer: plugin.DefaultGRPCServer, + }) } ``` -The `Name` method returns a plugin's name. -The `Version` method returns a plugin's version. -The `Init` method initializes a plugin with the provided `AppOptions`. -The io.Closer is used to shut down the plugin service. +We will introduce a plugin loading system that will return `(interface{}, error)`. +This provides the advantage of using versioned plugins where the plugin interface and gRPC protocol change over time. +In addition, it allows for building independent plugin that can expose different parts of the system over gRPC. -For the purposes of this ADR we introduce a single kind of plugin- a state streaming plugin. -We will define a `StateStreamingPlugin` interface which extends the above `Plugin` interface to support a state streaming service. +```go +func NewStreamingPlugin(name string, logLevel string) (interface{}, error) { + logger := hclog.New(&hclog.LoggerOptions{ + Output: hclog.DefaultOutput, + Level: toHclogLevel(logLevel), + Name: fmt.Sprintf("plugin.%s", name), + }) + + // We're a host. Start by launching the streaming process. + env := os.Getenv(GetPluginEnvKey(name)) + client := plugin.NewClient(&plugin.ClientConfig{ + HandshakeConfig: HandshakeMap[name], + Plugins: PluginMap, + Cmd: exec.Command("sh", "-c", env), + Logger: logger, + AllowedProtocols: []plugin.Protocol{ + plugin.ProtocolNetRPC, plugin.ProtocolGRPC}, + }) + + // Connect via RPC + rpcClient, err := client.Client() + if err != nil { + return nil, err + } + + // Request streaming plugin + return rpcClient.Dispense(name) +} + +``` + +We propose a `RegisterStreamingPlugin` function for the App to register `NewStreamingPlugin`s with the App's BaseApp. +Streaming plugins can be of `Any` type; therefore, the function takes in an interface vs a concrete type. +For example, we could have plugins of `ABCIListener`, `WasmListener` or `IBCListener`. Note that `RegisterStreamingPluing` function +is helper function and not a requirement. Plugin registration can easily be moved from the App to the BaseApp directly. ```go -// StateStreamingPlugin interface for plugins that load a baseapp.StreamingService onto a baseapp.BaseApp -type StateStreamingPlugin interface { - // Register configures and registers the plugin streaming service with the BaseApp - Register(bApp *baseapp.BaseApp, marshaller codec.BinaryCodec, keys map[string]*types.KVStoreKey) error +// baseapp/streaming.go + +// RegisterStreamingPlugin registers streaming plugins with the App. +// This method returns an error if a plugin is not supported. +func RegisterStreamingPlugin( + bApp *BaseApp, + appOpts servertypes.AppOptions, + keys map[string]*types.KVStoreKey, + streamingPlugin interface{}, +) error { + switch t := streamingPlugin.(type) { + case ABCIListener: + registerABCIListenerPlugin(bApp, appOpts, keys, t) + default: + return fmt.Errorf("unexpected plugin type %T", t) + } + return nil +} +``` - // Start starts the background streaming process of the plugin streaming service - Start(wg *sync.WaitGroup) error +```go +func registerABCIListenerPlugin( + bApp *BaseApp, + appOpts servertypes.AppOptions, + keys map[string]*store.KVStoreKey, + abciListener ABCIListener, +) { + asyncKey := fmt.Sprintf("%s.%s.%s", StreamingTomlKey, StreamingABCITomlKey, StreamingABCIAsync) + async := cast.ToBool(appOpts.Get(asyncKey)) + stopNodeOnErrKey := fmt.Sprintf("%s.%s.%s", StreamingTomlKey, StreamingABCITomlKey, StreamingABCIStopNodeOnErrTomlKey) + stopNodeOnErr := cast.ToBool(appOpts.Get(stopNodeOnErrKey)) + keysKey := fmt.Sprintf("%s.%s.%s", StreamingTomlKey, StreamingABCITomlKey, StreamingABCIKeysTomlKey) + exposeKeysStr := cast.ToStringSlice(appOpts.Get(keysKey)) + exposedKeys := exposeStoreKeysSorted(exposeKeysStr, keys) + bApp.cms.AddListeners(exposedKeys) + bApp.SetStreamingService(abciListener) + bApp.stopNodeOnABCIListenerErr = stopNodeOnErr + bApp.abciListenersAsync = async +} +``` - // Plugin is the base Plugin interface - Plugin +```go +func exposeAll(list []string) bool { + for _, ele := range list { + if ele == "*" { + return true + } + } + return false +} + +func exposeStoreKeys(keysStr []string, keys map[string]*types.KVStoreKey) []types.StoreKey { + var exposeStoreKeys []types.StoreKey + if exposeAll(keysStr) { + exposeStoreKeys = make([]types.StoreKey, 0, len(keys)) + for _, storeKey := range keys { + exposeStoreKeys = append(exposeStoreKeys, storeKey) + } + } else { + exposeStoreKeys = make([]types.StoreKey, 0, len(keysStr)) + for _, keyStr := range keysStr { + if storeKey, ok := keys[keyStr]; ok { + exposeStoreKeys = append(exposeStoreKeys, storeKey) + } + } + } + // sort storeKeys for deterministic output + sort.SliceStable(exposeStoreKeys, func(i, j int) bool { + return exposeStoreKeys[i].Name() < exposeStoreKeys[j].Name() + }) + + return exposeStoreKeys } ``` -The `Register` method is used during App construction to register the plugin's streaming service with an App's BaseApp using the BaseApp's `SetStreamingService` method. -The `Start` method is used during App construction to start the registered plugin streaming services and maintain synchronization with them. +The `NewStreamingPlugin` and `RegisterStreamingPlugin` functions are used to register a plugin with the App's BaseApp. e.g. in `NewSimApp`: ```go func NewSimApp( - logger log.Logger, - db dbm.DB, - traceStore io.Writer, - loadLatest bool, - appOpts servertypes.AppOptions, - baseAppOptions ...func(*baseapp.BaseApp), + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), ) *SimApp { - ... - - keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, - minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, - evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, - ) - - pluginsOnKey := fmt.Sprintf("%s.%s", plugin.PLUGINS_TOML_KEY, plugin.PLUGINS_ON_TOML_KEY) - if cast.ToBool(appOpts.Get(pluginsOnKey)) { - // this loads the preloaded and any plugins found in `plugins.dir` - pluginLoader, err := loader.NewPluginLoader(appOpts, logger) - if err != nil { - // handle error - } - - // initialize the loaded plugins - if err := pluginLoader.Initialize(); err != nil { - // handle error - } - - // register the plugin(s) with the BaseApp - if err := pluginLoader.Inject(bApp, appCodec, keys); err != nil { - // handle error - } - - // start the plugin services, optionally use wg to synchronize shutdown using io.Closer - wg := new(sync.WaitGroup) - if err := pluginLoader.Start(wg); err != nil { - // handler error - } - } + ... - ... + keys := sdk.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + ) - return app -} -``` + ... + + // register streaming services + streamingCfg := cast.ToStringMap(appOpts.Get(baseapp.StreamingTomlKey)) + for service := range streamingCfg { + pluginKey := fmt.Sprintf("%s.%s.%s", baseapp.StreamingTomlKey, service, baseapp.StreamingPluginTomlKey) + pluginName := strings.TrimSpace(cast.ToString(appOpts.Get(pluginKey))) + if len(pluginName) > 0 { + logLevel := cast.ToString(appOpts.Get(flags.FlagLogLevel)) + plugin, err := streaming.NewStreamingPlugin(pluginName, logLevel) + if err != nil { + tmos.Exit(err.Error()) + } + if err := baseapp.RegisterStreamingPlugin(bApp, appOpts, keys, plugin); err != nil { + tmos.Exit(err.Error()) + } + } + } + return app +``` #### Configuration -The plugin system will be configured within an app's app.toml file. +The plugin system will be configured within an App's TOML configuration files. ```toml -[plugins] - on = false # turn the plugin system, as a whole, on or off - enabled = ["list", "of", "plugin", "names", "to", "enable"] - dir = "the directory to load non-preloaded plugins from; defaults to cosmos-sdk/plugin/plugins" -``` - -There will be three parameters for configuring the plugin system: `plugins.on`, `plugins.enabled` and `plugins.dir`. -`plugins.on` is a bool that turns on or off the plugin system at large, `plugins.dir` directs the system to a directory -to load plugins from, and `plugins.enabled` provides `opt-in` semantics to plugin names to enable (including preloaded plugins). +# gRPC streaming +[streaming] -Configuration of a given plugin is ultimately specific to the plugin, but we will introduce some standards here: +# ABCI streaming service +[streaming.abci] -Plugin TOML configuration should be split into separate sub-tables for each kind of plugin (e.g. `plugins.streaming`). +# The plugin version to use for ABCI listening +plugin = "abci_v1" -Within these sub-tables, the parameters for a specific plugin of that kind are included in another sub-table (e.g. `plugins.streaming.file`). -It is generally expected, but not required, that a streaming service plugin can be configured with a set of store keys -(e.g. `plugins.streaming.file.keys`) for the stores it listens to and a flag (e.g. `plugins.streaming.file.halt_app_on_delivery_error`) -that signifies whether the service operates in a fire-and-forget capacity, or stop the BaseApp when an error occurs in -any of `ListenBeginBlock`, `ListenEndBlock` and `ListenDeliverTx`. +# List of kv store keys to listen to for state changes. +# Set to ["*"] to expose all keys. +keys = ["*"] -e.g. +# Enable abciListeners to run asynchronously. +# When abciListenersAsync=false and stopNodeOnABCIListenerErr=false listeners will run synchronized but will not stop the node. +# When abciListenersAsync=true stopNodeOnABCIListenerErr will be ignored. +async = false -```toml -[plugins] - on = false # turn the plugin system, as a whole, on or off - enabled = ["list", "of", "plugin", "names", "to", "enable"] - dir = "the directory to load non-preloaded plugins from; defaults to " - [plugins.streaming] # a mapping of plugin-specific streaming service parameters, mapped to their plugin name - [plugins.streaming.file] # the specific parameters for the file streaming service plugin - keys = ["list", "of", "store", "keys", "we", "want", "to", "expose", "for", "this", "streaming", "service"] - write_dir = "path to the write directory" - prefix = "optional prefix to prepend to the generated file names" - halt_app_on_delivery_error = "false" # false == fire-and-forget; true == stop the application - [plugins.streaming.kafka] - keys = [] - topic_prefix = "block" # Optional prefix for topic names where data will be stored. - flush_timeout_ms = 5000 # Flush and wait for outstanding messages and requests to complete delivery when calling `StreamingService.Close(). (milliseconds) - halt_app_on_delivery_error = true # Whether or not to halt the application when plugin fails to deliver message(s). - ... +# Whether to stop the node on message deliver error. +stop-node-on-err = true ``` +There will be four parameters for configuring `ABCIListener` plugin: `streaming.abci.plugin`, `streaming.abci.keys`, `streaming.abci.async` and `streaming.abci.stop-node-on-err`. +`streaming.abci.plugin` is the name of the plugin we want to use for streaming, `streaming.abci.keys` is a set of store keys for stores it listens to, +`streaming.abci.async` is bool enabling asynchronous listening and `streaming.abci.stop-node-on-err` is a bool that stops the node when true and when operating +on synchronized mode `streaming.abci.async=false`. Note that `streaming.abci.stop-node-on-err=true` will be ignored if `streaming.abci.async=true`. + +The configuration above support additional streaming plugins by adding the plugin to the `[streaming]` configuration section +and registering the plugin with `RegisterStreamingPlugin` helper function. + +Note the that each plugin must include `streaming.{service}.plugin` property as it is a requirement for doing the lookup and registration of the plugin +with the App. All other properties are unique to the individual services. + #### Encoding and decoding streams ADR-038 introduces the interfaces and types for streaming state changes out from KVStores, associating this @@ -553,7 +806,7 @@ These changes will provide a means of subscribing to KVStore state changes in re ### Backwards Compatibility -* This ADR changes the `CommitMultiStore` interface, implementations supporting the previous version of these interfaces will not support the new ones +* This ADR changes the `CommitMultiStore` interface, implementations supporting the previous version of this interface will not support the new one ### Positive @@ -561,7 +814,7 @@ These changes will provide a means of subscribing to KVStore state changes in re ### Negative -* Changes `CommitMultiStore`interface +* Changes `CommitMultiStore` interface and its implementations ### Neutral diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-040-storage-and-smt-state-commitments.md b/versioned_docs/version-0.47/integrate/architecture/adr-040-storage-and-smt-state-commitments.md index f60e3adcf..b089bfb1a 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-040-storage-and-smt-state-commitments.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-040-storage-and-smt-state-commitments.md @@ -23,7 +23,7 @@ In the current design, IAVL is used for both data storage and as a Merkle Tree f * Each edge traversal requires a DB query. * Creating snapshots is [expensive](https://github.com/cosmos/cosmos-sdk/issues/7215#issuecomment-684804950). It takes about 30 seconds to export less than 100 MB of state (as of March 2020). * Updates in IAVL may trigger tree reorganization and possible O(log(n)) hashes re-computation, which can become a CPU bottleneck. -* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/node.md +* The node structure is pretty expensive - it contains a standard tree node elements (key, value, left and right element) and additional metadata such as height, version (which is not required by the Cosmos SDK). The entire node is hashed, and that hash is used as the key in the underlying database, [ref](https://github.com/cosmos/iavl/blob/master/docs/node/03-node.md ). Moreover, the IAVL project lacks support and a maintainer and we already see better and well-established alternatives. Instead of optimizing the IAVL, we are looking into other solutions for both storage and state commitments. diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-042-group-module.md b/versioned_docs/version-0.47/integrate/architecture/adr-042-group-module.md index 52e94327d..834ec455e 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-042-group-module.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-042-group-module.md @@ -22,7 +22,7 @@ The legacy amino multi-signature mechanism of the Cosmos SDK has certain limitat * It requires `legacy_amino` sign mode ([#8141](https://github.com/cosmos/cosmos-sdk/issues/8141)). While the group module is not meant to be a total replacement for the current multi-signature accounts, it provides a solution to the limitations described above, with a more flexible key management system where keys can be added, updated or removed, as well as configurable thresholds. -It's meant to be used with other access control modules such as [`x/feegrant`](./adr-029-fee-grant-module.md) ans [`x/authz`](adr-030-authz-module.md) to simplify key management for individuals and organizations. +It's meant to be used with other access control modules such as [`x/feegrant`](adr-029-fee-grant-module.md) ans [`x/authz`](adr-030-authz-module.md) to simplify key management for individuals and organizations. The proof of concept of the group module can be found in https://github.com/regen-network/regen-ledger/tree/master/proto/regen/group/v1alpha1 and https://github.com/regen-network/regen-ledger/tree/master/x/group. diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-044-protobuf-updates-guidelines.md b/versioned_docs/version-0.47/integrate/architecture/adr-044-protobuf-updates-guidelines.md index a5ea31316..245adcffe 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-044-protobuf-updates-guidelines.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-044-protobuf-updates-guidelines.md @@ -78,7 +78,7 @@ Protobuf supports the [`deprecated` field option](https://developers.google.com/ As an example, the Cosmos SDK v0.42 to v0.43 update contained two Protobuf-breaking changes, listed below. Instead of bumping the package versions from `v1beta1` to `v1`, the SDK team decided to follow this guideline, by reverting the breaking changes, marking those changes as deprecated, and modifying the node implementation when processing messages with deprecated fields. More specifically: * The Cosmos SDK recently removed support for [time-based software upgrades](https://github.com/cosmos/cosmos-sdk/pull/8849). As such, the `time` field has been marked as deprecated in `cosmos.upgrade.v1beta1.Plan`. Moreover, the node will reject any proposal containing an upgrade Plan whose `time` field is non-empty. -* The Cosmos SDK now supports [governance split votes](./adr-037-gov-split-vote.md). When querying for votes, the returned `cosmos.gov.v1beta1.Vote` message has its `option` field (used for 1 vote option) deprecated in favor of its `options` field (allowing multiple vote options). Whenever possible, the SDK still populates the deprecated `option` field, that is, if and only if the `len(options) == 1` and `options[0].Weight == 1.0`. +* The Cosmos SDK now supports [governance split votes](adr-037-gov-split-vote.md). When querying for votes, the returned `cosmos.gov.v1beta1.Vote` message has its `option` field (used for 1 vote option) deprecated in favor of its `options` field (allowing multiple vote options). Whenever possible, the SDK still populates the deprecated `option` field, that is, if and only if the `len(options) == 1` and `options[0].Weight == 1.0`. #### 3. Fields MUST NOT be renamed diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-045-check-delivertx-middlewares.md b/versioned_docs/version-0.47/integrate/architecture/adr-045-check-delivertx-middlewares.md index 60172977c..756fa5a2d 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-045-check-delivertx-middlewares.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-045-check-delivertx-middlewares.md @@ -224,12 +224,12 @@ While the app developer can define and compose the middlewares of their choice, | TxDecoderMiddleware | This middleware takes in transaction raw bytes, and decodes them into a `sdk.Tx`. It replaces the `baseapp.txDecoder` field, so that BaseApp stays as thin as possible. Since most middlewares read the contents of the `sdk.Tx`, the TxDecoderMiddleware should be run first in the middleware stack. | | {Antehandlers} | Each antehandler is converted to its own middleware. These middlewares perform signature verification, fee deductions and other validations on the incoming transaction. | | IndexEventsTxMiddleware | This is a simple middleware that chooses which events to index in Tendermint. Replaces `baseapp.indexEvents` (which unfortunately still exists in baseapp too, because it's used to index Begin/EndBlock events) | -| RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery described in [ADR-022](./adr-022-custom-panic-handling.md). | +| RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery described in [ADR-022](adr-022-custom-panic-handling.md). | | GasTxMiddleware | This replaces the [`Setup`](https://github.com/cosmos/cosmos-sdk/blob/v0.43.0/x/auth/ante/setup.go) Antehandler. It sets a GasMeter on sdk.Context. Note that before, GasMeter was set on sdk.Context inside the antehandlers, and there was some mess around the fact that antehandlers had their own panic recovery system so that the GasMeter could be read by baseapp's recovery system. Now, this mess is all removed: one middleware sets GasMeter, another one handles recovery. | ### Similarities and Differences between Antehandlers and Middlewares -The middleware-based design builds upon the existing antehandlers design described in [ADR-010](./adr-010-modular-antehandler.md). Even though the final decision of ADR-010 was to go with the "Simple Decorators" approach, the middleware design is actually very similar to the other [Decorator Pattern](./adr-010-modular-antehandler.md#decorator-pattern) proposal, also used in [weave](https://github.com/iov-one/weave). +The middleware-based design builds upon the existing antehandlers design described in [ADR-010](adr-010-modular-antehandler.md). Even though the final decision of ADR-010 was to go with the "Simple Decorators" approach, the middleware design is actually very similar to the other [Decorator Pattern](adr-010-modular-antehandler.md#decorator-pattern) proposal, also used in [weave](https://github.com/iov-one/weave). #### Similarities with Antehandlers diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-047-extend-upgrade-plan.md b/versioned_docs/version-0.47/integrate/architecture/adr-047-extend-upgrade-plan.md index 0df030062..3a4f3aac4 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-047-extend-upgrade-plan.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-047-extend-upgrade-plan.md @@ -2,7 +2,7 @@ ## Changelog -- Nov, 23, 2021: Initial Draft +* Nov, 23, 2021: Initial Draft ## Status @@ -19,9 +19,9 @@ The `upgrade` module in conjunction with Cosmovisor are designed to facilitate a Users submit a software upgrade governance proposal containing an upgrade `Plan`. The [Plan](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/proto/cosmos/upgrade/v1beta1/upgrade.proto#L12) currently contains the following fields: -- `name`: A short string identifying the new version. -- `height`: The chain height at which the upgrade is to be performed. -- `info`: A string containing information about the upgrade. +* `name`: A short string identifying the new version. +* `height`: The chain height at which the upgrade is to be performed. +* `info`: A string containing information about the upgrade. The `info` string can be anything. However, Cosmovisor will try to use the `info` field to automatically download a new version of the blockchain executable. @@ -40,6 +40,7 @@ Both `DAEMON_HOME` and `DAEMON_NAME` are [environment variables used to configur Currently, there is no mechanism that makes Cosmovisor run a command after the upgraded chain has been restarted. The current upgrade process has this timeline: + 1. An upgrade governance proposal is submitted and approved. 1. The upgrade height is reached. 1. The `x/upgrade` module writes the `upgrade_info.json` file. @@ -78,7 +79,7 @@ message UpgradeInstructions { ``` All fields in the `UpgradeInstructions` are optional. -- `pre_run` is a command to run prior to the upgraded chain restarting. +* `pre_run` is a command to run prior to the upgraded chain restarting. If defined, it will be executed after halting and downloading the new artifact but before restarting the upgraded chain. The working directory this command runs from MUST be `{DAEMON_HOME}/cosmovisor/{upgrade name}`. This command MUST behave the same as the current [pre-upgrade](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/docs/migrations/pre-upgrade.md) command. @@ -91,12 +92,12 @@ All fields in the `UpgradeInstructions` are optional. | `30` | `pre-upgrade` command was executed but failed. This fails the entire upgrade. | | `31` | `pre-upgrade` command was executed but failed. But the command is retried until exit code `1` or `30` are returned. | If defined, then the app supervisors (e.g. Cosmovisor) MUST NOT run `app pre-run`. -- `post_run` is a command to run after the upgraded chain has been started. If defined, this command MUST be only executed at most once by an upgrading node. +* `post_run` is a command to run after the upgraded chain has been started. If defined, this command MUST be only executed at most once by an upgrading node. The output and exit code SHOULD be logged but SHOULD NOT affect the running of the upgraded chain. The working directory this command runs from MUST be `{DAEMON_HOME}/cosmovisor/{upgrade name}`. -- `artifacts` define items to be downloaded. +* `artifacts` define items to be downloaded. It SHOULD have only one entry per platform. -- `description` contains human-readable information about the upgrade and might contain references to external resources. +* `description` contains human-readable information about the upgrade and might contain references to external resources. It SHOULD NOT be used for structured processing information. ```protobuf @@ -108,20 +109,20 @@ message Artifact { } ``` -- `platform` is a required string that SHOULD be in the format `{OS}/{CPU}`, e.g. `"linux/amd64"`. +* `platform` is a required string that SHOULD be in the format `{OS}/{CPU}`, e.g. `"linux/amd64"`. The string `"any"` SHOULD also be allowed. An `Artifact` with a `platform` of `"any"` SHOULD be used as a fallback when a specific `{OS}/{CPU}` entry is not found. That is, if an `Artifact` exists with a `platform` that matches the system's OS and CPU, that should be used; otherwise, if an `Artifact` exists with a `platform` of `any`, that should be used; otherwise no artifact should be downloaded. -- `url` is a required URL string that MUST conform to [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt). +* `url` is a required URL string that MUST conform to [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt). A request to this `url` MUST return either an executable file or an archive containing either `bin/{DAEMON_NAME}` or `{DAEMON_NAME}`. The URL should not contain checksum - it should be specified by the `checksum` attribute. -- `checksum` is a checksum of the expected result of a request to the `url`. +* `checksum` is a checksum of the expected result of a request to the `url`. It is not required, but is recommended. If provided, it MUST be a hex encoded checksum string. Tools utilizing these `UpgradeInstructions` MUST fail if a `checksum` is provided but is different from the checksum of the result returned by the `url`. -- `checksum_algo` is a string identify the algorithm used to generate the `checksum`. +* `checksum_algo` is a string identify the algorithm used to generate the `checksum`. Recommended algorithms: `sha256`, `sha512`. Algorithms also supported (but not recommended): `sha1`, `md5`. If a `checksum` is provided, a `checksum_algo` MUST also be provided. @@ -140,6 +141,7 @@ We will update the creation of the `upgrade-info.json` file to include the `Upgr We will update the optional validation available via CLI to account for the new `Plan` structure. We will add the following validation: + 1. If `UpgradeInstructions` are provided: 1. There MUST be at least one entry in `artifacts`. 1. All of the `artifacts` MUST have a unique `platform`. @@ -165,6 +167,7 @@ If the `upgrade-info.json` file does not contain any `UpgradeInstructions`, exis We will update Cosmovisor to look for and handle the new `UpgradeInstructions` in `upgrade-info.json`. If the `UpgradeInstructions` are provided, we will do the following: + 1. The `info` field will be ignored. 1. The `artifacts` field will be used to identify the artifact to download based on the `platform` that Cosmovisor is running in. 1. If a `checksum` is provided (either in the field or as a query param in the `url`), and the downloaded artifact has a different checksum, the upgrade process will be interrupted and Cosmovisor will exit with an error. @@ -179,6 +182,7 @@ We will deprecate the use of the `info` field for anything other than human read A warning will be logged if the `info` field is used to define the assets (either by URL or JSON). The new upgrade timeline is very similar to the current one. Changes are in bold: + 1. An upgrade governance proposal is submitted and approved. 1. The upgrade height is reached. 1. The `x/upgrade` module writes the `upgrade_info.json` file **(now possibly with `UpgradeInstructions`)**. @@ -199,6 +203,7 @@ Additionally, current behavior will be maintained when no `UpgradeInstructions` ### Forwards Compatibility In order to utilize the `UpgradeInstructions` as part of a software upgrade, both of the following must be true: + 1. The chain must already be using a sufficiently advanced version of the Cosmos SDK. 1. The chain's nodes must be using a sufficiently advanced version of Cosmovisor. @@ -237,9 +242,9 @@ In order to utilize the `UpgradeInstructions` as part of a software upgrade, bot ## References -- [Current upgrade.proto](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/proto/cosmos/upgrade/v1beta1/upgrade.proto) -- [Upgrade Module README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/x/upgrade/spec/README.md) -- [Cosmovisor README](https://github.com/cosmos/cosmos-sdk/blob/cosmovisor/v1.0.0/cosmovisor/README.md) -- [Pre-upgrade README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/docs/migrations/pre-upgrade.md) -- [Draft/POC PR #10032](https://github.com/cosmos/cosmos-sdk/pull/10032) -- [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt) +* [Current upgrade.proto](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/proto/cosmos/upgrade/v1beta1/upgrade.proto) +* [Upgrade Module README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/x/upgrade/spec/README.md) +* [Cosmovisor README](https://github.com/cosmos/cosmos-sdk/blob/cosmovisor/v1.0.0/cosmovisor/README.md) +* [Pre-upgrade README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/docs/migrations/pre-upgrade.md) +* [Draft/POC PR #10032](https://github.com/cosmos/cosmos-sdk/pull/10032) +* [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-049-state-sync-hooks.md b/versioned_docs/version-0.47/integrate/architecture/adr-049-state-sync-hooks.md index f1df759e2..c7353aa3b 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-049-state-sync-hooks.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-049-state-sync-hooks.md @@ -2,8 +2,8 @@ ## Changelog -- Jan 19, 2022: Initial Draft -- Apr 29, 2022: Safer extension snapshotter interface +* Jan 19, 2022: Initial Draft +* Apr 29, 2022: Safer extension snapshotter interface ## Status @@ -150,13 +150,13 @@ But for applications that does not have the state data outside of the IAVL tree ### Positive -- State maintained outside of IAVL tree like CosmWasm blobs can create snapshots by implementing extension snapshotters, and being fetched by new clients via state-sync. +* State maintained outside of IAVL tree like CosmWasm blobs can create snapshots by implementing extension snapshotters, and being fetched by new clients via state-sync. ### Negative ### Neutral -- All modules that maintain state outside of IAVL tree need to implement `ExtensionSnapshotter` and the snapshot `Manager` need to call `RegisterExtensions` when setting up the application. +* All modules that maintain state outside of IAVL tree need to implement `ExtensionSnapshotter` and the snapshot `Manager` need to call `RegisterExtensions` when setting up the application. ## Further Discussions @@ -169,6 +169,6 @@ Test cases for an implementation are mandatory for ADRs that are affecting conse ## References -- https://github.com/cosmos/cosmos-sdk/pull/10961 -- https://github.com/cosmos/cosmos-sdk/issues/7340 -- https://hackmd.io/gJoyev6DSmqqkO667WQlGw +* https://github.com/cosmos/cosmos-sdk/pull/10961 +* https://github.com/cosmos/cosmos-sdk/issues/7340 +* https://hackmd.io/gJoyev6DSmqqkO667WQlGw diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex1.md b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex1.md index db2d3d67c..13deec921 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex1.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex1.md @@ -2,8 +2,11 @@ ## Changelog -- Dec 06, 2021: Initial Draft -- Feb 07, 2022: Draft read and concept-ACKed by the Ledger team. +* Dec 06, 2021: Initial Draft +* Feb 07, 2022: Draft read and concept-ACKed by the Ledger team. +* Dec 01, 2022: Remove `Object: ` prefix on Any header screen. +* Dec 13, 2022: Sign over bytes hash when bytes length > 32. +* Mar 27, 2023: Update `Any` value renderer to omit message header screen. ## Status @@ -19,63 +22,68 @@ Value Renderers describe how values of different Protobuf types should be encode ### Protobuf `number` -- Applies to: - - protobuf numeric integer types (`int{32,64}`, `uint{32,64}`, `sint{32,64}`, `fixed{32,64}`, `sfixed{32,64}`) - - strings whose `customtype` is `github.com/cosmos/cosmos-sdk/types.Int` or `github.com/cosmos/cosmos-sdk/types.Dec` - - bytes whose `customtype` is `github.com/cosmos/cosmos-sdk/types.Int` or `github.com/cosmos/cosmos-sdk/types.Dec` -- Trailing decimal zeroes are always removed -- Formatting with `'`s for every three integral digits. -- Usage of `.` to denote the decimal delimiter. +* Applies to: + * protobuf numeric integer types (`int{32,64}`, `uint{32,64}`, `sint{32,64}`, `fixed{32,64}`, `sfixed{32,64}`) + * strings whose `customtype` is `github.com/cosmos/cosmos-sdk/types.Int` or `github.com/cosmos/cosmos-sdk/types.Dec` + * bytes whose `customtype` is `github.com/cosmos/cosmos-sdk/types.Int` or `github.com/cosmos/cosmos-sdk/types.Dec` +* Trailing decimal zeroes are always removed +* Formatting with `'`s for every three integral digits. +* Usage of `.` to denote the decimal delimiter. #### Examples -- `1000` (uint64) -> `1'000` -- `"1000000.00"` (string representing a Dec) -> `1'000'000` -- `"1000000.10"` (string representing a Dec) -> `1'000'000.1` +* `1000` (uint64) -> `1'000` +* `"1000000.00"` (string representing a Dec) -> `1'000'000` +* `"1000000.10"` (string representing a Dec) -> `1'000'000.1` ### `coin` -- Applies to `cosmos.base.v1beta1.Coin`. -- Denoms are converted to `display` denoms using `Metadata` (if available). **This requires a state query**. The definition of `Metadata` can be found in the [bank Protobuf definition](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/bank.proto#L79-L108). If the `display` field is empty or nil, then we do not perform any denom conversion. -- Amounts are converted to `display` denom amounts and rendered as `number`s above - - We do not change the capitalization of the denom. In practice, `display` denoms are stored in lowercase in state (e.g. `10 atom`), however they are often showed in UPPERCASE in everyday life (e.g. `10 ATOM`). Value renderers keep the case used in state, but we may recommend chains changing the denom metadata to be uppercase for better user display. -- One space between the denom and amount (e.g. `10 atom`). -- In the future, IBC denoms could maybe be converted to DID/IIDs, if we can find a robust way for doing this (ex. `cosmos:cosmos:hub:bank:denom:atom`) +* Applies to `cosmos.base.v1beta1.Coin`. +* Denoms are converted to `display` denoms using `Metadata` (if available). **This requires a state query**. The definition of `Metadata` can be found in the [bank protobuf definition](https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.bank.v1beta1#cosmos.bank.v1beta1.Metadata). If the `display` field is empty or nil, then we do not perform any denom conversion. +* Amounts are converted to `display` denom amounts and rendered as `number`s above + * We do not change the capitalization of the denom. In practice, `display` denoms are stored in lowercase in state (e.g. `10 atom`), however they are often showed in UPPERCASE in everyday life (e.g. `10 ATOM`). Value renderers keep the case used in state, but we may recommend chains changing the denom metadata to be uppercase for better user display. +* One space between the denom and amount (e.g. `10 atom`). +* In the future, IBC denoms could maybe be converted to DID/IIDs, if we can find a robust way for doing this (ex. `cosmos:cosmos:hub:bank:denom:atom`) #### Examples -- `1000000000uatom` -> `["1'000 atom"]`, because atom is the metadata's display denom. +* `1000000000uatom` -> `["1'000 atom"]`, because atom is the metadata's display denom. ### `coins` -- an array of `coin` is display as the concatenation of each `coin` encoded as the specification above, the joined together with the delimiter `", "` (a comma and a space, no quotes around). -- the list of coins is ordered by unicode code point of the display denom: `A-Z` < `a-z`. For example, the string `aAbBcC` would be sorted `ABCabc`. +* an array of `coin` is display as the concatenation of each `coin` encoded as the specification above, the joined together with the delimiter `", "` (a comma and a space, no quotes around). +* the list of coins is ordered by unicode code point of the display denom: `A-Z` < `a-z`. For example, the string `aAbBcC` would be sorted `ABCabc`. + * if the coins list had 0 items in it then it'll be rendered as `zero` ### Example -- `["3cosm", "2000000uatom"]` -> `2 atom, 3 COSM` (assuming the display denoms are `atom` and `COSM`) -- `["10atom", "20Acoin"]` -> `20 Acoin, 10 atom` (assuming the display denoms are `atom` and `Acoin`) +* `["3cosm", "2000000uatom"]` -> `2 atom, 3 COSM` (assuming the display denoms are `atom` and `COSM`) +* `["10atom", "20Acoin"]` -> `20 Acoin, 10 atom` (assuming the display denoms are `atom` and `Acoin`) +* `[]` -> `zero` ### `repeated` -- Applies to all `repeated` fields, except `cosmos.tx.v1beta1.TxBody#Messages`, which has a particular encoding (see [ADR-050](./adr-050-sign-mode-textual.md)). -- A repeated type has the following template: +* Applies to all `repeated` fields, except `cosmos.tx.v1beta1.TxBody#Messages`, which has a particular encoding (see [ADR-050](adr-050-sign-mode-textual.md)). +* A repeated type has the following template: ``` - has - (/): +: + (/): - (/): + (/): End of . ``` where: -- `message_name` is the name of the Protobuf message which holds the `repeated` field, -- `int` is the length of the array, -- `field_name` is the Protobuf field name of the repeated field, - - add an optional `s` at the end if ` > 1` and the `field_name` doesn't already end with `s`. +* `field_name` is the Protobuf field name of the repeated field +* `field_kind`: + * if the type of the repeated field is a message, `field_kind` is the message name + * if the type of the repeated field is an enum, `field_kind` is the enum name + * in any other case, `field_kind` is the protobuf primitive type (e.g. "string" or "bytes") +* `int` is the length of the array +* `index` is one based index of the repeated field #### Examples @@ -104,20 +112,21 @@ End of Allowed messages ### `message` -- Applies to Protobuf messages whose name does not start with `Msg` - - For `sdk.Msg`s, please see [ADR-050](./adr-050-sign-mode-textual.md) - - alternatively, we can decide to add a protobuf option to denote messages that are `sdk.Msg`s. -- Field names follow [sentence case](https://en.wiktionary.org/wiki/sentence_case) - - replace `_` with a spaces - - capitalize first letter of the setence -- Field names are ordered by their Protobuf field number -- Nesting: - - if a field contains a nested message, we value-render the underlying message using the template: +* Applies to all Protobuf messages that do not have a custom encoding. +* Field names follow [sentence case](https://en.wiktionary.org/wiki/sentence_case) + * replace each `_` with a space + * capitalize first letter of the sentence +* Field names are ordered by their Protobuf field number +* Screen title is the field name, and screen content is the value. +* Nesting: + * if a field contains a nested message, we value-render the underlying message using the template: + ``` : <1st line of value-rendered message> > // Notice the `>` prefix. ``` - - `>` character is used to denote nesting. For each additional level of nesting, add `>`. + + * `>` character is used to denote nesting. For each additional level of nesting, add `>`. #### Examples @@ -150,26 +159,20 @@ we get the following encoding for the `Vote` message: ``` Vote object > Proposal id: 4 -> Vote: cosmos1abc...def +> Voter: cosmos1abc...def > Options: 2 WeightedVoteOptions > Options (1/2): WeightedVoteOption object ->> Option: Yes +>> Option: VOTE_OPTION_YES >> Weight: 0.7 > Options (2/2): WeightedVoteOption object ->> Option: No +>> Option: VOTE_OPTION_NO >> Weight: 0.3 > End of Options ``` ### Enums -- String case convention: snake case to sentence case -- Allow optional annotation for textual name (TBD) -- Algorithm: - - convert enum name (`VoteOption`) to snake_case (`VOTE_OPTION`) - - truncate that prefix + `_` from the enum name if it exists (`VOTE_OPTION_` gets stripped from `VOTE_OPTION_YES` -> `YES`) - - convert rest to sentence case: `YES` -> `Yes` - - in summary: `VOTE_OPTION_YES` -> `Yes` +* Show the enum variant name as string. #### Examples @@ -177,18 +180,23 @@ See example above with `message Vote{}`. ### `google.protobuf.Any` -- Applies to `google.protobuf.Any` -- Rendered as: +* Applies to `google.protobuf.Any` +* Rendered as: ``` -Object: + > ``` +There is however one exception: when the underlying message is a Protobuf message that does not have a custom encoding, then the message header screen is omitted, and one level of indentation is removed. + +Messages that have a custom encoding, including `google.protobuf.Timestamp`, `google.protobuf.Duration`, `google.protobuf.Any`, `cosmos.base.v1beta1.Coin`, and messages that have an app-defined custom encoding, will preserve their header and indentation level. + #### Examples +Message header screen is stripped, one-level of indentation removed: ``` -Object: /cosmos.gov.v1.Vote +/cosmos.gov.v1.Vote > Proposal id: 4 > Vote: cosmos1abc...def > Options: 2 WeightedVoteOptions @@ -201,6 +209,12 @@ Object: /cosmos.gov.v1.Vote > End of Options ``` +Message with custom encoding: +``` +/cosmos.base.v1beta1.Coin +> 10uatom +``` + ### `google.protobuf.Timestamp` Rendered using [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) (a @@ -245,14 +259,32 @@ Negative durations will be indicated with a leading minus sign (`-`). Examples: -- `1 day` -- `30 days` -- `-1 day, 12 hours` -- `3 hours, 0 minutes, 53.025 seconds` +* `1 day` +* `30 days` +* `-1 day, 12 hours` +* `3 hours, 0 minutes, 53.025 seconds` ### bytes -- Bytes are rendered in hexadecimal, all capital letters, without the `0x` prefix. +* Bytes of length shorter or equal to 35 are rendered in hexadecimal, all capital letters, without the `0x` prefix. +* Bytes of length greater than 35 are hashed using SHA256. The rendered text is `SHA-256=`, followed by the 32-byte hash, in hexadecimal, all capital letters, without the `0x` prefix. +* The hexadecimal string is finally separated into groups of 4 digits, with a space `' '` as separator. If the bytes length is odd, the 2 remaining hexadecimal characters are at the end. + +The number 35 was chosen because it is the longest length where the hashed-and-prefixed representation is longer than the original data directly formatted, using the 3 rules above. More specifically: +- a 35-byte array will have 70 hex characters, plus 17 space characters, resulting in 87 characters. +- byte arrays starting from length 36 will be be hashed to 32 bytes, which is 64 hex characters plus 15 spaces, and with the `SHA-256=` prefix, it takes 87 characters. +Also, secp256k1 public keys have length 33, so their Textual representation is not their hashed value, which we would like to avoid. + +Note: Data longer than 35 bytes are not rendered in a way that can be inverted. See ADR-050's [section about invertability](adr-050-sign-mode-textual.md#invertible-rendering) for a discussion. + +#### Examples + +Inputs are displayed as byte arrays. + +* `[0]`: `00` +* `[0,1,2]`: `0001 02` +* `[0,1,2,..,34]`: `0001 0203 0405 0607 0809 0A0B 0C0D 0E0F 1011 1213 1415 1617 1819 1A1B 1C1D 1E1F 2021 22` +* `[0,1,2,..,35]`: `SHA-256=5D7E 2D9B 1DCB C85E 7C89 0036 A2CF 2F9F E7B6 6554 F2DF 08CE C6AA 9C0A 25C9 9C21` ### address bytes @@ -264,7 +296,7 @@ Strings are rendered as-is. ### Default Values -- Default Protobuf values for each field are skipped. +* Default Protobuf values for each field are skipped. #### Example @@ -288,6 +320,10 @@ TestData object > Signer: cosmos1abc ``` +### bool + +Boolean values are rendered as `True` or `False`. + ### [ABANDONED] Custom `msg_title` instead of Msg `type_url` _This paragraph is in the Annex for informational purposes only, and will be removed in a next update of the ADR._ @@ -295,8 +331,8 @@ _This paragraph is in the Annex for informational purposes only, and will be rem
Click to see abandoned idea. -- all protobuf messages to be used with `SIGN_MODE_TEXTUAL` CAN have a short title associated with them that can be used in format strings whenever the type URL is explicitly referenced via the `cosmos.msg.v1.textual.msg_title` Protobuf message option. -- if this option is not specified for a Msg, then the Protobuf fully qualified name will be used. +* all protobuf messages to be used with `SIGN_MODE_TEXTUAL` CAN have a short title associated with them that can be used in format strings whenever the type URL is explicitly referenced via the `cosmos.msg.v1.textual.msg_title` Protobuf message option. +* if this option is not specified for a Msg, then the Protobuf fully qualified name will be used. ```protobuf message MsgSend { @@ -304,11 +340,11 @@ message MsgSend { } ``` -- they MUST be unique per message, per chain +* they MUST be unique per message, per chain #### Examples -- `cosmos.gov.v1.MsgVote` -> `governance v1 vote` +* `cosmos.gov.v1.MsgVote` -> `governance v1 vote` #### Best Pratices @@ -316,7 +352,7 @@ We recommend to use this option only for `Msg`s whose Protobuf fully qualified n In those cases, we recommend to drop the version (e.g. `v1`) in the string if there's only one version of the module on chain. This way, the bijective mapping can figure out which message each string corresponds to. If multiple Protobuf versions of the same module exist on the same chain, we recommend keeping the first `msg_title` with version, and the second `msg_title` with version (e.g. `v2`): -- `mychain.mymodule.v1.MsgDo` -> `mymodule do something` -- `mychain.mymodule.v2.MsgDo` -> `mymodule v2 do something` +* `mychain.mymodule.v1.MsgDo` -> `mymodule do something` +* `mychain.mymodule.v2.MsgDo` -> `mymodule v2 do something`
diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex2.md b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex2.md index d4037a50e..9bd0f3f47 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex2.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual-annex2.md @@ -2,7 +2,7 @@ ## Changelog -- Oct 3, 2022: Initial Draft +* Oct 3, 2022: Initial Draft ## Status @@ -47,42 +47,42 @@ As an illustration of these principles, here is an example algorithm for presentation on a device which can display a single 80-character line of printable ASCII characters: -- The presentation is broken into lines, and each line is presented in +* The presentation is broken into lines, and each line is presented in sequence, with user controls for going forward or backward a line. -- Expert mode screens are only presented if the device is in expert mode. +* Expert mode screens are only presented if the device is in expert mode. -- Each line of the screen starts with a number of `>` characters equal +* Each line of the screen starts with a number of `>` characters equal to the screen's indentation level, followed by a `+` character if this isn't the first line of the screen, followed by a space if either a `>` or a `+` has been emitted, or if this header is followed by a `>`, `+`, or space. -- If the line ends with whitespace or an `@` character, an additional `@` +* If the line ends with whitespace or an `@` character, an additional `@` character is appended to the line. -- The following ASCII control characters or backslash (`\`) are converted +* The following ASCII control characters or backslash (`\`) are converted to a backslash followed by a letter code, in the manner of string literals in many languages: - - a: U+0007 alert or bell - - b: U+0008 backspace - - f: U+000C form feed - - n: U+000A line feed - - r: U+000D carriage return - - t: U+0009 horizontal tab - - v: U+000B vertical tab - - `\`: U+005C backslash + * a: U+0007 alert or bell + * b: U+0008 backspace + * f: U+000C form feed + * n: U+000A line feed + * r: U+000D carriage return + * t: U+0009 horizontal tab + * v: U+000B vertical tab + * `\`: U+005C backslash -- All other ASCII control characters, plus non-ASCII Unicode code points, +* All other ASCII control characters, plus non-ASCII Unicode code points, are shown as either: - - `\u` followed by 4 uppercase hex chacters for code points + * `\u` followed by 4 uppercase hex chacters for code points in the basic multilingual plane (BMP). - - `\U` followed by 8 uppercase hex characters for other code points. + * `\U` followed by 8 uppercase hex characters for other code points. -- The screen will be broken into multiple lines to fit the 80-character +* The screen will be broken into multiple lines to fit the 80-character limit, considering the above transformations in a way that attempts to minimize the number of lines generated. Expanded control or Unicode characters are never split across lines. diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual.md b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual.md index 4fa83852e..efa4ace48 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-050-sign-mode-textual.md @@ -2,27 +2,36 @@ ## Changelog -- Dec 06, 2021: Initial Draft. -- Feb 07, 2022: Draft read and concept-ACKed by the Ledger team. -- May 16, 2022: Change status to Accepted. -- Aug 11, 2022: Require signing over tx raw bytes. -- Sep 07, 2022: Add custom `Msg`-renderers. -- Sep 18, 2022: Structured format instead of lines of text +* Dec 06, 2021: Initial Draft. +* Feb 07, 2022: Draft read and concept-ACKed by the Ledger team. +* May 16, 2022: Change status to Accepted. +* Aug 11, 2022: Require signing over tx raw bytes. +* Sep 07, 2022: Add custom `Msg`-renderers. +* Sep 18, 2022: Structured format instead of lines of text +* Nov 23, 2022: Specify CBOR encoding. +* Dec 01, 2022: Link to examples in separate JSON file. +* Dec 06, 2022: Re-ordering of envelope screens. +* Dec 14, 2022: Mention exceptions for invertability. +* Jan 23, 2023: Switch Screen.Text to Title+Content. +* Mar 07, 2023: Change SignDoc from array to struct containing array. +* Mar 20, 2023: Introduce a spec version initialized to 0. ## Status Accepted. Implementation started. Small value renderers details still need to be polished. +Spec version: 0. + ## Abstract This ADR specifies SIGN_MODE_TEXTUAL, a new string-based sign mode that is targetted at signing with hardware devices. ## Context -Protobuf-based SIGN_MODE_DIRECT was introduced in [ADR-020](./adr-020-protobuf-transaction-encoding.md) and is intended to replace SIGN_MODE_LEGACY_AMINO_JSON in most situations, such as mobile wallets and CLI keyrings. However, the [Ledger](https://www.ledger.com/) hardware wallet is still using SIGN_MODE_LEGACY_AMINO_JSON for displaying the sign bytes to the user. Hardware wallets cannot transition to SIGN_MODE_DIRECT as: +Protobuf-based SIGN_MODE_DIRECT was introduced in [ADR-020](adr-020-protobuf-transaction-encoding.md) and is intended to replace SIGN_MODE_LEGACY_AMINO_JSON in most situations, such as mobile wallets and CLI keyrings. However, the [Ledger](https://www.ledger.com/) hardware wallet is still using SIGN_MODE_LEGACY_AMINO_JSON for displaying the sign bytes to the user. Hardware wallets cannot transition to SIGN_MODE_DIRECT as: -- SIGN_MODE_DIRECT is binary-based and thus not suitable for display to end-users. Technically, hardware wallets could simply display the sign bytes to the user. But this would be considered as blind signing, and is a security concern. -- hardware cannot decode the protobuf sign bytes due to memory constraints, as the Protobuf definitions would need to be embedded on the hardware device. +* SIGN_MODE_DIRECT is binary-based and thus not suitable for display to end-users. Technically, hardware wallets could simply display the sign bytes to the user. But this would be considered as blind signing, and is a security concern. +* hardware cannot decode the protobuf sign bytes due to memory constraints, as the Protobuf definitions would need to be embedded on the hardware device. In an effort to remove Amino from the SDK, a new sign mode needs to be created for hardware devices. [Initial discussions](https://github.com/cosmos/cosmos-sdk/issues/6513) propose a text-based sign mode, which this ADR formally specifies. @@ -45,7 +54,7 @@ or to introduce or conclude a larger grouping. The text can contain the full range of Unicode code points, including control characters and nul. The device is responsible for deciding how to display characters it cannot render natively. -See [annex 2](./adr-050-sign-mode-textual-annex2.md) for guidance. +See [annex 2](adr-050-sign-mode-textual-annex2.md) for guidance. Screens have a non-negative indentation level to signal composite or nested structures. Indentation level zero is the top level. @@ -75,6 +84,14 @@ Note that the existence of an inverse function ensures that the rendered text contains the full information of the original transaction, not a hash or subset. +We make an exception for invertibility for data which are too large to +meaningfully display, such as byte strings longer than 32 bytes. We may then +selectively render them with a cryptographically-strong hash. In these cases, +it is still computationally infeasible to find a different transaction which +has the same rendering. However, we must ensure that the hash computation is +simple enough to be reliably executed independently, so at least the hash is +itself reasonably verifiable when the raw byte string is not. + ### Chain State The rendering function (and parsing function) may depend on the current chain state. @@ -114,21 +131,56 @@ in the rendering. The SignDoc for `SIGN_MODE_TEXTUAL` is formed from a data structure like: -``` +```go type Screen struct { - Text string text // possibly size limited to, e.g. 255 characters - Indent uint8 // size limited to something small like 16 or 32 + Title string // possibly size limited to, advised to 64 characters + Content string // possibly size limited to, advised to 255 characters + Indent uint8 // size limited to something small like 16 or 32 Expert bool } -type SignDocTextual = []Screen +type SignDocTextual struct { + Screens []Screen +} ``` We do not plan to use protobuf serialization to form the sequence of bytes that will be tranmitted and signed, in order to keep the decoder simple. We will use [CBOR](https://cbor.io) ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html)) instead. +The encoding is defined by the following CDDL ([RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)): + +``` +;;; CDDL (RFC 8610) Specification of SignDoc for SIGN_MODE_TEXTUAL. +;;; Must be encoded using CBOR deterministic encoding (RFC 8949, section 4.2.1). -TODO: specify the details of the CBOR encoding. +;; A Textual document is a struct containing one field: an array of screens. +sign_doc = { + screens_key: [* screen], +} + +;; The key is an integer to keep the encoding small. +screens_key = 1 + +;; A screen consists of a text string, an indentation, and the expert flag, +;; represented as an integer-keyed map. All entries are optional +;; and MUST be omitted from the encoding if empty, zero, or false. +;; Text defaults to the empty string, indent defaults to zero, +;; and expert defaults to false. +screen = { + ? title_key: tstr, + ? content_key: tstr, + ? indent_key: uint, + ? expert_key: bool, +} + +;; Keys are small integers to keep the encoding small. +title_key = 1 +content_key = 2 +indent_key = 3 +expert_key = 4 +``` + +Defining the sign_doc as directly an array of screens has also been considered. However, given the possibility of future iterations of this specification, using a single-keyed struct has been chosen over the former proposal, as structs allow for easier backwards-compatibility. ## Details @@ -143,29 +195,30 @@ We define "transaction envelope" as all data in a transaction that is not in the ``` Chain ID: Account number: -*Public Key: Sequence: - // See #8. -Fee: // See value renderers for coins encoding. -*Fee payer: // Skipped if no fee_payer set -*Fee granter: // Skipped if no fee_granter set -Memo: // Skipped if no memo set +Address: +*Public Key: +This transaction has Message(s) // Pluralize "Message" only when int>1 +> Message (/): // See value renderers for Any rendering. +End of Message +Memo: // Skipped if no memo set. +Fee: // See value renderers for coins rendering. +*Fee payer: // Skipped if no fee_payer set. +*Fee granter: // Skipped if no fee_granter set. +Tip: // Skippted if no tip. +Tipper: *Gas Limit: -*Timeout Height: // Skipped if no timeout_height set -Tipper: // If there's a tip -Tip: -*This transaction has body extension: // Skipped if no body extension options -* -*This transaction has body non-critical extensions: // Skipped if no body non-critical extension options -* // See value renderers for Any and array encoding. -*This transaction has body auth info extensions: // Skipped if no auth info extension options -* -*This transaction has other signers: // Skipped if there is only one signer -*Signer (/): -*Public Key: -*Sequence: +*Timeout Height: // Skipped if no timeout_height set. +*Other signer: SignerInfo // Skipped if the transaction only has 1 signer. +*> Other signer (/): *End of other signers -*Hash of raw bytes: // Hex encoding of bytes defined in #10, to prevent tx hash malleability. +*Extension options: Any: // Skipped if no body extension options +*> Extension options (/): +*End of extension options +*Non critical extension options: Any: // Skipped if no body non critical extension options +*> Non critical extension options (/): +*End of Non critical extension options +*Hash of raw bytes: // Hex encoding of bytes defined, to prevent tx hash malleability. ``` ### Encoding of the Transaction Body @@ -192,7 +245,6 @@ message Grant { message MsgGrant { option (cosmos.msg.v1.signer) = "granter"; - option (cosmos.msg.v1.textual.type_url) = "authz v1beta1 grant"; string granter = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; string grantee = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -213,13 +265,13 @@ End of transaction messages Application developers may choose to not follow default renderer value output for their own `Msg`s. In this case, they can implement their own custom `Msg` renderer. This is similar to [EIP4430](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4430.md), where the smart contract developer chooses the description string to be shown to the end user. -This is done by setting the `cosmos.msg.v1.textual.expert_custom_renderer` Protobuf option to a non-empty string. This option CAN ONLY be set on a Protobuf message representing transaction message object (implementing `sdk.Msg` interface). +This is done by setting the `cosmos.msg.textual.v1.expert_custom_renderer` Protobuf option to a non-empty string. This option CAN ONLY be set on a Protobuf message representing transaction message object (implementing `sdk.Msg` interface). ```protobuf message MsgFooBar { // Optional comments to describe in human-readable language the formatting // rules of the custom renderer. - option (cosmos.msg.v1.textual.expert_custom_renderer) = ""; + option (cosmos.msg.textual.v1.expert_custom_renderer) = ""; // proto fields } @@ -240,320 +292,45 @@ Recall that the transaction bytes merklelized on chain are the Protobuf binary s ``` where: -- `++` denotes concatenation, -- `HEX` is the hexadecimal representation of the bytes, all in capital letters, no `0x` prefix, -- and `len()` is encoded as a Big-Endian uint64. + +* `++` denotes concatenation, +* `HEX` is the hexadecimal representation of the bytes, all in capital letters, no `0x` prefix, +* and `len()` is encoded as a Big-Endian uint64. This is to prevent transaction hash malleability. The point #1 about invertiblity assures that transaction `body` and `auth_info` values are not malleable, but the transaction hash still might be malleable with point #1 only, because the SIGN_MODE_TEXTUAL strings don't follow the byte ordering defined in `body_bytes` and `auth_info_bytes`. Without this hash, a malicious validator or exchange could intercept a transaction, modify its transaction hash _after_ the user signed it using SIGN_MODE_TEXTUAL (by tweaking the byte ordering inside `body_bytes` or `auth_info_bytes`), and then submit it to Tendermint. -By including this hash in the SIGN_MODE_TEXTUAL signing payload, we keep the same level of guarantees as [SIGN_MODE_DIRECT](./adr-020-protobuf-transaction-encoding.md). +By including this hash in the SIGN_MODE_TEXTUAL signing payload, we keep the same level of guarantees as [SIGN_MODE_DIRECT](adr-020-protobuf-transaction-encoding.md). These bytes are only shown in expert mode, hence the leading `*`. -## Additional Formatting by the Hardware Device +## Updates to the current specification -See [annex 2](./adr-050-sign-mode-textual-annex2.md). +The current specification is not set in stone, and future iterations are to be expected. We distinguish two categories of updates to this specification: -## Examples +1. Updates that require changes of the hardware device embedded application. +2. Updates that only modify the envelope and the value renderers. -#### Example 1: Simple `MsgSend` - -JSON: - -```json -{ - "body": { - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...abc", - "to": "cosmos1...def", - "amount": [ - { - "denom": "uatom", - "amount": 10000000 - } - ] - } - ] - }, - "auth_info": { - "signer_infos": [ - { - "public_key": "iQ...==", - "mode_info": { "single": { "mode": "SIGN_MODE_TEXTUAL" } }, - "sequence": 2 - } - ], - "fee": { - "amount": [ - { - "denom": "atom", - "amount": 0.002 - } - ], - "gas_limit": 100000 - } - }, - // Additional SignerData. - "chain_id": "simapp-1", - "account_number": 10 -} -``` +Updates in the 1st category include changes of the `Screen` struct or its corresponding CBOR encoding. This type of updates require a modification of the hardware signer application, to be able to decode and parse the new types. Backwards-compatibility must also be guaranteed, so that the new hardware application works with existing versions of the SDK. These updates require the coordination of multiple parties: SDK developers, hardware application developers (currently: Zondax), and client-side developers (e.g. CosmJS). Furthermore, a new submission of the hardware device application may be necessary, which, dependending on the vendor, can take some time. As such, we recommend to avoid this type of updates as much as possible. -SIGN_MODE_TEXTUAL: +Updates in the 2nd category include changes to any of the value renderers or to the transaction envelope. For example, the ordering of fields in the envelope can be swapped, or the timestamp formatting can be modified. Since SIGN_MODE_TEXTUAL sends `Screen`s to the hardware device, this type of change do not need a hardware wallet application update. They are however state-machine-breaking, and must be documented as such. They require the coordination of SDK developers with client-side developers (e.g. CosmJS), so that the updates are released on both sides close to each other in time. -``` -Chain ID: simapp-1 -Account number: 10 -*Public Key: iQ...== // Hex pubkey -Sequence: 2 -This transaction has 1 message: -Message (1/1): bank v1beta1 send coins -From: cosmos1...abc -To: cosmos1...def -Amount: 10 atom // Conversion from uatom to atom using value renderers -End of transaction messages -Fee: 0.002 atom -*Gas: 100'000 -*Hash of raw bytes: -``` +We define a spec version, which is an integer that must be incremented on each update of either category. This spec version will be exposed by the SDK's implementation, and can be communicated to clients. For example, SDK v0.48 might use the spec version 1, and SDK v0.49 might use 2; thanks to this versioning, clients can know how to craft SIGN_MODE_TEXTUAL transactions based on the target SDK version. -#### Example 2: Multi-Msg Transaction with 3 signers - -#### Example 3: Legacy Multisig - -#### Example 4: Fee Payer with Tips - -```json -{ - "body": { - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...tipper", - "to": "cosmos1...abc", - "amount": [ - { - "denom": "uatom", - "amount": 10000000 - } - ] - } - ] - }, - "auth_info": { - "signer_infos": [ - { - "public_key": "iQ...==", - "mode_info": { "single": { "mode": "SIGN_MODE_DIRECT_AUX" } }, - "sequence": 42 - }, - { - "public_key": "iR...==", - "mode_info": { "single": { "mode": "SIGN_MODE_TEXTUAL" } }, - "sequence": 2 - } - ], - "fee": { - "amount": [ - { - "denom": "atom", - "amount": 0.002 - } - ], - "gas_limit": 100000, - "payer": "cosmos1...feepayer" - }, - "tip": { - "amount": [ - { - "denom": "ibc/CDC4587874B85BEA4FCEC3CEA5A1195139799A1FEE711A07D972537E18FDA39D", - "amount": 200 - } - ], - "tipper": "cosmos1...tipper" - } - }, - // Additional SignerData. - "chain_id": "simapp-1", - "account_number": 10 -} -``` +The current spec version is defined in the "Status" section, on the top of this document. It is initialized to `0` to allow flexibility in choosing how to define future versions, as it would allow adding a field either in the SignDoc Go struct or in Protobuf in a backwards-compatible way. -SIGN_MODE_TEXTUAL for the feepayer: +## Additional Formatting by the Hardware Device -``` -Chain ID: simapp-1 -Account number: 10 -*Public Key: iR...== -Sequence: 2 -This transaction has 1 message: -Message (1/1): bank v1beta1 send coins -From: cosmos1...abc -To: cosmos1...def -Amount: 10 atom -End of transaction messages -Fee: 0.002 atom -Fee Payer: cosmos1...feepayer -Tipper: cosmos1...tipper -Tip: 200 ibc/CDC4587874B85BEA4FCEC3CEA5A1195139799A1FEE711A07D972537E18FDA39D -*Gas: 100'000 -*This transaction has 1 other signer: -*Signer (1/2): -*Public Key: iQ...== -*Sign mode: Direct Aux -*Sequence: 42 -*End of other signers -*Hash of raw bytes: -``` +See [annex 2](adr-050-sign-mode-textual-annex2.md). -#### Example 5: Complex Transaction with Nested Messages - -JSON: - -```json -{ - "body": { - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...abc", - "to": "cosmos1...def", - "amount": [ - { - "denom": "uatom", - "amount": 10000000 - } - ] - }, - { - "@type": "/cosmos.gov.v1.MsgSubmitProposal", - "proposer": "cosmos1...ghi", - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...jkl", - "to": "cosmos1...mno", - "amount": [ - { - "denom": "uatom", - "amount": 20000000 - } - ] - }, - { - "@type": "/cosmos.authz.v1beta1.MsgExec", - "grantee": "cosmos1...pqr", - "msgs": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...stu", - "to": "cosmos1...vwx", - "amount": [ - { - "denom": "uatom", - "amount": 30000000 - } - ] - }, - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from": "cosmos1...abc", - "to": "cosmos1...def", - "amount": [ - { - "denom": "uatom", - "amount": 40000000 - } - ] - } - ] - } - ], - "initial_deposit": [ - { - "denom": "atom", - "amount": 100.01 - } - ] - } - ] - }, - "auth_info": { - "signer_infos": [ - { - "public_key": "iQ...==", - "mode_info": { "single": { "mode": "SIGN_MODE_TEXTUAL" } }, - "sequence": 2 - }, - { - "public_key": "iR...==", - "mode_info": { "single": { "mode": "SIGN_MODE_DIRECT" } }, - "sequence": 42 - } - ], - "fee": { - "amount": [ - { - "denom": "atom", - "amount": 0.002 - } - ], - "gas_limit": 100000 - } - }, - // Additional SignerData. - "chain_id": "simapp-1", - "account_number": 10 -} -} -``` +## Examples -SIGN_MODE_TEXTUAL for 1st signer `cosmos1...abc`: +1. A minimal MsgSend: [see transaction](https://github.com/cosmos/cosmos-sdk/blob/094abcd393379acbbd043996024d66cd65246fb1/tx/textual/internal/testdata/e2e.json#L2-L70). +2. A transaction with a bit of everything: [see transaction](https://github.com/cosmos/cosmos-sdk/blob/094abcd393379acbbd043996024d66cd65246fb1/tx/textual/internal/testdata/e2e.json#L71-L270). -``` -Chain ID: simapp-1 -Account number: 10 -*Public Key: iQ...== -Sequence: 2 -This transaction has 2 messages: -Message (1/2): bank v1beta1 send coins -From: cosmos1...abc -To: cosmos1...def -Amount: 10 atom -Message (2/2): gov v1 submit proposal -Messages: 2 Messages -> Message (1/2): bank v1beta1 send coins -> From: cosmos1...jkl -> To: cosmos1...mno -> Amount: 20 atom -> Message (2/2): authz v1beta exec -> Grantee: cosmos1...pqr -> Msgs: 2 Msgs ->> Msg (1/2): bank v1beta1 send coins ->> From: cosmos1...stu ->> To: cosmos1...vwx ->> Amount: 30 atom ->> Msg (2/2): bank v1beta1 send coins ->> From: cosmos1...abc ->> To: cosmos1...def ->> Amount: 40 atom -> End of Msgs -End of transaction messages -Proposer: cosmos1...ghi -Initial Deposit: 100.01 atom -End of transaction messages -Fee: 0.002 atom -*Gas: 100'000 -*This transaction has 1 other signer: -*Signer (2/2): -*Public Key: iR...== -*Sign mode: Direct -*Sequence: 42 -*End of other signers -*Hash of raw bytes: -``` +The examples below are stored in a JSON file with the following fields: +- `proto`: the representation of the transaction in ProtoJSON, +- `screens`: the transaction rendered into SIGN_MODE_TEXTUAL screens, +- `cbor`: the sign bytes of the transaction, which is the CBOR encoding of the screens. ## Consequences @@ -563,30 +340,30 @@ SIGN_MODE_TEXTUAL is purely additive, and doesn't break any backwards compatibil ### Positive -- Human-friendly way of signing in hardware devices. -- Once SIGN_MODE_TEXTUAL is shipped, SIGN_MODE_LEGACY_AMINO_JSON can be deprecated and removed. On the longer term, once the ecosystem has totally migrated, Amino can be totally removed. +* Human-friendly way of signing in hardware devices. +* Once SIGN_MODE_TEXTUAL is shipped, SIGN_MODE_LEGACY_AMINO_JSON can be deprecated and removed. On the longer term, once the ecosystem has totally migrated, Amino can be totally removed. ### Negative -- Some fields are still encoded in non-human-readable ways, such as public keys in hexadecimal. -- New ledger app needs to be released, still unclear +* Some fields are still encoded in non-human-readable ways, such as public keys in hexadecimal. +* New ledger app needs to be released, still unclear ### Neutral -- If the transaction is complex, the string array can be arbitrarily long, and some users might just skip some screens and blind sign. +* If the transaction is complex, the string array can be arbitrarily long, and some users might just skip some screens and blind sign. ## Further Discussions -- Some details on value renderers need to be polished, see [Annex 1](./adr-050-sign-mode-textual-annex1.md). -- Are ledger apps able to support both SIGN_MODE_LEGACY_AMINO_JSON and SIGN_MODE_TEXTUAL at the same time? -- Open question: should we add a Protobuf field option to allow app developers to overwrite the textual representation of certain Protobuf fields and message? This would be similar to Ethereum's [EIP4430](https://github.com/ethereum/EIPs/pull/4430), where the contract developer decides on the textual representation. -- Internationalization. +* Some details on value renderers need to be polished, see [Annex 1](adr-050-sign-mode-textual-annex1.md). +* Are ledger apps able to support both SIGN_MODE_LEGACY_AMINO_JSON and SIGN_MODE_TEXTUAL at the same time? +* Open question: should we add a Protobuf field option to allow app developers to overwrite the textual representation of certain Protobuf fields and message? This would be similar to Ethereum's [EIP4430](https://github.com/ethereum/EIPs/pull/4430), where the contract developer decides on the textual representation. +* Internationalization. ## References -- [Annex 1](./adr-050-sign-mode-textual-annex1.md) +* [Annex 1](adr-050-sign-mode-textual-annex1.md) -- Initial discussion: https://github.com/cosmos/cosmos-sdk/issues/6513 -- Living document used in the working group: https://hackmd.io/fsZAO-TfT0CKmLDtfMcKeA?both -- Working group meeting notes: https://hackmd.io/7RkGfv_rQAaZzEigUYhcXw -- Ethereum's "Described Transactions" https://github.com/ethereum/EIPs/pull/4430 +* Initial discussion: https://github.com/cosmos/cosmos-sdk/issues/6513 +* Living document used in the working group: https://hackmd.io/fsZAO-TfT0CKmLDtfMcKeA?both +* Working group meeting notes: https://hackmd.io/7RkGfv_rQAaZzEigUYhcXw +* Ethereum's "Described Transactions" https://github.com/ethereum/EIPs/pull/4430 diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-053-go-module-refactoring.md b/versioned_docs/version-0.47/integrate/architecture/adr-053-go-module-refactoring.md index 9093ae9d9..d15c39019 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-053-go-module-refactoring.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-053-go-module-refactoring.md @@ -52,6 +52,7 @@ as to how to do this, with some developers arguing for larger vs smaller module scopes. There are pros and cons to both approaches (which will be discussed below in the [Consequences](#consequences) section), but the approach being adopted is the following: + * a go module should generally be scoped to a specific coherent set of functionality (such as math, errors, store, etc.) * when code is removed from the core SDK and moved to a new module path, every @@ -106,4 +107,4 @@ the Cosmos SDK Framework Working Group. * https://github.com/cosmos/cosmos-sdk/discussions/10162 * https://github.com/cosmos/cosmos-sdk/discussions/10582 * https://github.com/cosmos/cosmos-sdk/pull/10779 -* https://github.com/cosmos/cosmos-sdk/pull/11788 \ No newline at end of file +* https://github.com/cosmos/cosmos-sdk/pull/11788 diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-054-semver-compatible-modules.md b/versioned_docs/version-0.47/integrate/architecture/adr-054-semver-compatible-modules.md new file mode 100644 index 000000000..ed2a5f3f6 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/architecture/adr-054-semver-compatible-modules.md @@ -0,0 +1,728 @@ +# ADR 054: Semver Compatible SDK Modules + +## Changelog + +* 2022-04-27: First draft + +## Status + +DRAFT + +## Abstract + +In order to move the Cosmos SDK to a system of decoupled semantically versioned +modules which can be composed in different combinations (ex. staking v3 with +bank v1 and distribution v2), we need to reassess how we organize the API surface +of modules to avoid problems with go semantic import versioning and +circular dependencies. This ADR explores various approaches we can take to +addressing these issues. + +## Context + +There has been [a fair amount of desire](https://github.com/cosmos/cosmos-sdk/discussions/10162) +in the community for semantic versioning in the SDK and there has been significant +movement to splitting SDK modules into [standalone go modules](https://github.com/cosmos/cosmos-sdk/issues/11899). +Both of these will ideally allow the ecosystem to move faster because we won't +be waiting for all dependencies to update synchronously. For instance, we could +have 3 versions of the core SDK compatible with the latest 2 releases of +CosmWasm as well as 4 different versions of staking . This sort of setup would +allow early adopters to aggressively integrate new versions, while allowing +more conservative users to be selective about which versions they're ready for. + +In order to achieve this, we need to solve the following problems: + +1. because of the way [go semantic import versioning](https://research.swtch.com/vgo-import) (SIV) + works, moving to SIV naively will actually make it harder to achieve these goals +2. circular dependencies between modules need to be broken to actually release + many modules in the SDK independently +3. pernicious minor version incompatibilities introduced through correctly + [evolving protobuf schemas](https://developers.google.com/protocol-buffers/docs/proto3#updating) + without correct [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering) + +Note that all the following discussion assumes that the proto file versioning and state machine versioning of a module +are distinct in that: + +* proto files are maintained in a non-breaking way (using something + like [buf breaking](https://docs.buf.build/breaking/overview) + to ensure all changes are backwards compatible) +* proto file versions get bumped much less frequently, i.e. we might maintain `cosmos.bank.v1` through many versions + of the bank module state machine +* state machine breaking changes are more common and ideally this is what we'd want to semantically version with + go modules, ex. `x/bank/v2`, `x/bank/v3`, etc. + +### Problem 1: Semantic Import Versioning Compatibility + +Consider we have a module `foo` which defines the following `MsgDoSomething` and that we've released its state +machine in go module `example.com/foo`: + +```protobuf +package foo.v1; + +message MsgDoSomething { + string sender = 1; + uint64 amount = 2; +} + +service Msg { + DoSomething(MsgDoSomething) returns (MsgDoSomethingResponse); +} +``` + +Now consider that we make a revision to this module and add a new `condition` field to `MsgDoSomething` and also +add a new validation rule on `amount` requiring it to be non-zero, and that following go semantic versioning we +release the next state machine version of `foo` as `example.com/foo/v2`. + +```protobuf +// Revision 1 +package foo.v1; + +message MsgDoSomething { + string sender = 1; + + // amount must be a non-zero integer. + uint64 amount = 2; + + // condition is an optional condition on doing the thing. + // + // Since: Revision 1 + Condition condition = 3; +} +``` + +Approaching this naively, we would generate the protobuf types for the initial +version of `foo` in `example.com/foo/types` and we would generate the protobuf +types for the second version in `example.com/foo/v2/types`. + +Now let's say we have a module `bar` which talks to `foo` using this keeper +interface which `foo` provides: + +```go +type FooKeeper interface { + DoSomething(MsgDoSomething) error +} +``` + +#### Scenario A: Backward Compatibility: Newer Foo, Older Bar + +Imagine we have a chain which uses both `foo` and `bar` and wants to upgrade to +`foo/v2`, but the `bar` module has not upgraded to `foo/v2`. + +In this case, the chain will not be able to upgrade to `foo/v2` until `bar` +has upgraded its references to `example.com/foo/types.MsgDoSomething` to +`example.com/foo/v2/types.MsgDoSomething`. + +Even if `bar`'s usage of `MsgDoSomething` has not changed at all, the upgrade +will be impossible without this change because `example.com/foo/types.MsgDoSomething` +and `example.com/foo/v2/types.MsgDoSomething` are fundamentally different +incompatible structs in the go type system. + +#### Scenario B: Forward Compatibility: Older Foo, Newer Bar + +Now let's consider the reverse scenario, where `bar` upgrades to `foo/v2` +by changing the `MsgDoSomething` reference to `example.com/foo/v2/types.MsgDoSomething` +and releases that as `bar/v2` with some other changes that a chain wants. +The chain, however, has decided that it thinks the changes in `foo/v2` are too +risky and that it'd prefer to stay on the initial version of `foo`. + +In this scenario, it is impossible to upgrade to `bar/v2` without upgrading +to `foo/v2` even if `bar/v2` would have worked 100% fine with `foo` other +than changing the import path to `MsgDoSomething` (meaning that `bar/v2` +doesn't actually use any new features of `foo/v2`). + +Now because of the way go semantic import versioning works, we are locked +into either using `foo` and `bar` OR `foo/v2` and `bar/v2`. We cannot have +`foo` + `bar/v2` OR `foo/v2` + `bar`. The go type system doesn't allow this +even if both versions of these modules are otherwise compatible with each +other. + +#### Naive Mitigation + +A naive approach to fixing this would be to not regenerate the protobuf types +in `example.com/foo/v2/types` but instead just update `example.com/foo/types` +to reflect the changes needed for `v2` (adding `condition` and requiring +`amount` to be non-zero). Then we could release a patch of `example.com/foo/types` +with this update and use that for `foo/v2`. But this change is state machine +breaking for `v1`. It requires changing the `ValidateBasic` method to reject +the case where `amount` is zero, and it adds the `condition` field which +should be rejected based +on [ADR 020 unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering). +So adding these changes as a patch on `v1` is actually incorrect based on semantic +versioning. Chains that want to stay on `v1` of `foo` should not +be importing these changes because they are incorrect for `v1.` + +### Problem 2: Circular dependencies + +None of the above approaches allow `foo` and `bar` to be separate modules +if for some reason `foo` and `bar` depend on each other in different ways. +For instance, we can't have `foo` import `bar/types` while `bar` imports +`foo/types`. + +We have several cases of circular module dependencies in the SDK +(ex. staking, distribution and slashing) that are legitimate from a state machine +perspective. Without separating the API types out somehow, there would be +no way to independently semantically version these modules without some other +mitigation. + +### Problem 3: Handling Minor Version Incompatibilities + +Imagine that we solve the first two problems but now have a scenario where +`bar/v2` wants the option to use `MsgDoSomething.condition` which only `foo/v2` +supports. If `bar/v2` works with `foo` `v1` and sets `condition` to some non-nil +value, then `foo` will silently ignore this field resulting in a silent logic +possibly dangerous logic error. If `bar/v2` were able to check whether `foo` was +on `v1` or `v2` and dynamically, it could choose to only use `condition` when +`foo/v2` is available. Even if `bar/v2` were able to perform this check, however, +how do we know that it is always performing the check properly. Without +some sort of +framework-level [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering), +it is hard to know whether these pernicious hard to detect bugs are getting into +our app and a client-server layer such as [ADR 033: Inter-Module Communication](adr-033-protobuf-inter-module-comm.md) +may be needed to do this. + +## Solutions + +### Approach A) Separate API and State Machine Modules + +One solution (first proposed in https://github.com/cosmos/cosmos-sdk/discussions/10582) is to isolate all protobuf +generated code into a separate module +from the state machine module. This would mean that we could have state machine +go modules `foo` and `foo/v2` which could use a types or API go module say +`foo/api`. This `foo/api` go module would be perpetually on `v1.x` and only +accept non-breaking changes. This would then allow other modules to be +compatible with either `foo` or `foo/v2` as long as the inter-module API only +depends on the types in `foo/api`. It would also allow modules `foo` and `bar` +to depend on each other in that both of them could depend on `foo/api` and +`bar/api` without `foo` directly depending on `bar` and vice versa. + +This is similar to the naive mitigation described above except that it separates +the types into separate go modules which in and of itself could be used to +break circular module dependencies. It has the same problems as the naive solution, +otherwise, which we could rectify by: + +1. removing all state machine breaking code from the API module (ex. `ValidateBasic` and any other interface methods) +2. embedding the correct file descriptors for unknown field filtering in the binary + +#### Migrate all interface methods on API types to handlers + +To solve 1), we need to remove all interface implementations from generated +types and instead use a handler approach which essentially means that given +a type `X`, we have some sort of resolver which allows us to resolve interface +implementations for that type (ex. `sdk.Msg` or `authz.Authorization`). For +example: + +```go +func (k Keeper) DoSomething(msg MsgDoSomething) error { + var validateBasicHandler ValidateBasicHandler + err := k.resolver.Resolve(&validateBasic, msg) + if err != nil { + return err + } + + err = validateBasicHandler.ValidateBasic() + ... +} +``` + +In the case of some methods on `sdk.Msg`, we could replace them with declarative +annotations. For instance, `GetSigners` can already be replaced by the protobuf +annotation `cosmos.msg.v1.signer`. In the future, we may consider some sort +of protobuf validation framework (like https://github.com/bufbuild/protoc-gen-validate +but more Cosmos-specific) to replace `ValidateBasic`. + +#### Pinned FileDescriptor's + +To solve 2), state machine modules must be able to specify what the version of +the protobuf files was that they were built against. For instance if the API +module for `foo` upgrades to `foo/v2`, the original `foo` module still needs +a copy of the original protobuf files it was built with so that ADR 020 +unknown field filtering will reject `MsgDoSomething` when `condition` is +set. + +The simplest way to do this may be to embed the protobuf `FileDescriptor`s into +the module itself so that these `FileDescriptor`s are used at runtime rather +than the ones that are built into the `foo/api` which may be different. Using +[buf build](https://docs.buf.build/build/usage#output-format), [go embed](https://pkg.go.dev/embed), +and a build script we can probably come up with a solution for embedding +`FileDescriptor`s into modules that is fairly straightforward. + +#### Potential limitations to generated code + +One challenge with this approach is that it places heavy restrictions on what +can go in API modules and requires that most of this is state machine breaking. +All or most of the code in the API module would be generated from protobuf +files, so we can probably control this with how code generation is done, but +it is a risk to be aware of. + +For instance, we do code generation for the ORM that in the future could +contain optimizations that are state machine breaking. We +would either need to ensure very carefully that the optimizations aren't +actually state machine breaking in generated code or separate this generated code +out from the API module into the state machine module. Both of these mitigations +are potentially viable but the API module approach does require an extra level +of care to avoid these sorts of issues. + +#### Minor Version Incompatibilities + +This approach in and of itself does little to address any potential minor +version incompatibilities and the +requisite [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering). +Likely some sort of client-server routing layer which does this check such as +[ADR 033: Inter-Module communication](adr-033-protobuf-inter-module-comm.md) +is required to make sure that this is done properly. We could then allow +modules to perform a runtime check given a `MsgClient`, ex: + +```go +func (k Keeper) CallFoo() error { + if k.interModuleClient.MinorRevision(k.fooMsgClient) >= 2 { + k.fooMsgClient.DoSomething(&MsgDoSomething{Condition: ...}) + } else { + ... + } +} +``` + +To do the unknown field filtering itself, the ADR 033 router would need to use +the [protoreflect API](https://pkg.go.dev/google.golang.org/protobuf/reflect/protoreflect) +to ensure that no fields unknown to the receiving module are set. This could +result in an undesirable performance hit depending on how complex this logic is. + +### Approach B) Changes to Generated Code + +An alternate approach to solving the versioning problem is to change how protobuf code is generated and move modules +mostly or completely in the direction of inter-module communication as described +in [ADR 033](adr-033-protobuf-inter-module-comm.md). +In this paradigm, a module could generate all the types it needs internally - including the API types of other modules - +and talk to other modules via a client-server boundary. For instance, if `bar` needs to talk to `foo`, it could +generate its own version of `MsgDoSomething` as `bar/internal/foo/v1.MsgDoSomething` and just pass this to the +inter-module router which would somehow convert it to the version which foo needs (ex. `foo/internal.MsgDoSomething`). + +Currently, two generated structs for the same protobuf type cannot exist in the same go binary without special +build flags (see https://developers.google.com/protocol-buffers/docs/reference/go/faq#fix-namespace-conflict). +A relatively simple mitigation to this issue would be to set up the protobuf code to not register protobuf types +globally if they are generated in an `internal/` package. This will require modules to register their types manually +with the app-level level protobuf registry, this is similar to what modules already do with the `InterfaceRegistry` +and amino codec. + +If modules _only_ do ADR 033 message passing then a naive and non-performant solution for +converting `bar/internal/foo/v1.MsgDoSomething` +to `foo/internal.MsgDoSomething` would be marshaling and unmarshaling in the ADR 033 router. This would break down if +we needed to expose protobuf types in `Keeper` interfaces because the whole point is to try to keep these types +`internal/` so that we don't end up with all the import version incompatibilities we've described above. However, +because of the issue with minor version incompatibilities and the need +for [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering), +sticking with the `Keeper` paradigm instead of ADR 033 may be unviable to begin with. + +A more performant solution (that could maybe be adapted to work with `Keeper` interfaces) would be to only expose +getters and setters for generated types and internally store data in memory buffers which could be passed from +one implementation to another in a zero-copy way. + +For example, imagine this protobuf API with only getters and setters is exposed for `MsgSend`: + +```go +type MsgSend interface { + proto.Message + GetFromAddress() string + GetToAddress() string + GetAmount() []v1beta1.Coin + SetFromAddress(string) + SetToAddress(string) + SetAmount([]v1beta1.Coin) +} + +func NewMsgSend() MsgSend { return &msgSendImpl{memoryBuffers: ...} } +``` + +Under the hood, `MsgSend` could be implemented based on some raw memory buffer in the same way +that [Cap'n Proto](https://capnproto.org) +and [FlatBuffers](https://google.github.io/flatbuffers/) so that we could convert between one version of `MsgSend` +and another without serialization (i.e. zero-copy). This approach would have the added benefits of allowing zero-copy +message passing to modules written in other languages such as Rust and accessed through a VM or FFI. It could also make +unknown field filtering in inter-module communication simpler if we require that all new fields are added in sequential +order, ex. just checking that no field `> 5` is set. + +Also, we wouldn't have any issues with state machine breaking code on generated types because all the generated +code used in the state machine would actually live in the state machine module itself. Depending on how interface +types and protobuf `Any`s are used in other languages, however, it may still be desirable to take the handler +approach described in approach A. Either way, types implementing interfaces would still need to be registered +with an `InterfaceRegistry` as they are now because there would be no way to retrieve them via the global registry. + +In order to simplify access to other modules using ADR 033, a public API module (maybe even one +[remotely generated by Buf](https://docs.buf.build/bsr/remote-generation/go)) could be used by client modules instead +of requiring to generate all client types internally. + +The big downsides of this approach are that it requires big changes to how people use protobuf types and would be a +substantial rewrite of the protobuf code generator. This new generated code, however, could still be made compatible +with +the [`google.golang.org/protobuf/reflect/protoreflect`](https://pkg.go.dev/google.golang.org/protobuf/reflect/protoreflect) +API in order to work with all standard golang protobuf tooling. + +It is possible that the naive approach of marshaling/unmarshaling in the ADR 033 router is an acceptable intermediate +solution if the changes to the code generator are seen as too complex. However, since all modules would likely need +to migrate to ADR 033 anyway with this approach, it might be better to do this all at once. + +### Approach C) Don't address these issues + +If the above solutions are seen as too complex, we can also decide not to do anything explicit to enable better module +version compatibility, and break circular dependencies. + +In this case, when developers are confronted with the issues described above they can require dependencies to update in +sync (what we do now) or attempt some ad-hoc potentially hacky solution. + +One approach is to ditch go semantic import versioning (SIV) altogether. Some people have commented that go's SIV +(i.e. changing the import path to `foo/v2`, `foo/v3`, etc.) is too restrictive and that it should be optional. The +golang maintainers disagree and only officially support semantic import versioning. We could, however, take the +contrarian perspective and get more flexibility by using 0.x-based versioning basically forever. + +Module version compatibility could then be achieved using go.mod replace directives to pin dependencies to specific +compatible 0.x versions. For instance if we knew `foo` 0.2 and 0.3 were both compatible with `bar` 0.3 and 0.4, we +could use replace directives in our go.mod to stick to the versions of `foo` and `bar` we want. This would work as +long as the authors of `foo` and `bar` avoid incompatible breaking changes between these modules. + +Or, if developers choose to use semantic import versioning, they can attempt the naive solution described above +and would also need to use special tags and replace directives to make sure that modules are pinned to the correct +versions. + +Note, however, that all of these ad-hoc approaches, would be vulnerable to the minor version compatibility issues +described above unless [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering) +is properly addressed. + +### Approach D) Avoid protobuf generated code in public APIs + +An alternative approach would be to avoid protobuf generated code in public module APIs. This would help avoid the +discrepancy between state machine versions and client API versions at the module to module boundaries. It would mean +that we wouldn't do inter-module message passing based on ADR 033, but rather stick to the existing keeper approach +and take it one step further by avoiding any protobuf generated code in the keeper interface methods. + +Using this approach, our `foo.Keeper.DoSomething` method wouldn't have the generated `MsgDoSomething` struct (which +comes from the protobuf API), but instead positional parameters. Then in order for `foo/v2` to support the `foo/v1` +keeper it would simply need to implement both the v1 and v2 keeper APIs. The `DoSomething` method in v2 could have the +additional `condition` parameter, but this wouldn't be present in v1 at all so there would be no danger of a client +accidentally setting this when it isn't available. + +So this approach would avoid the challenge around minor version incompatibilities because the existing module keeper +API would not get new fields when they are added to protobuf files. + +Taking this approach, however, would likely require making all protobuf generated code internal in order to prevent +it from leaking into the keeper API. This means we would still need to modify the protobuf code generator to not +register `internal/` code with the global registry, and we would still need to manually register protobuf +`FileDescriptor`s (this is probably true in all scenarios). It may, however, be possible to avoid needing to refactor +interface methods on generated types to handlers. + +Also, this approach doesn't address what would be done in scenarios where modules still want to use the message router. +Either way, we probably still want a way to pass messages from one module to another router safely even if it's just for +use cases like `x/gov`, `x/authz`, CosmWasm, etc. That would still require most of the things outlined in approach (B), +although we could advise modules to prefer keepers for communicating with other modules. + +The biggest downside of this approach is probably that it requires a strict refactoring of keeper interfaces to avoid +generated code leaking into the API. This may result in cases where we need to duplicate types that are already defined +in proto files and then write methods for converting between the golang and protobuf version. This may end up in a lot +of unnecessary boilerplate and that may discourage modules from actually adopting it and achieving effective version +compatibility. Approaches (A) and (B), although heavy handed initially, aim to provide a system which once adopted +more or less gives the developer version compatibility for free with minimal boilerplate. Approach (D) may not be able +to provide such a straightforward system since it requires a golang API to be defined alongside a protobuf API in a +way that requires duplication and differing sets of design principles (protobuf APIs encourage additive changes +while golang APIs would forbid it). + +Other downsides to this approach are: +* no clear roadmap to supporting modules in other languages like Rust +* doesn't get us any closer to proper object capability security (one of the goals of ADR 033) +* ADR 033 needs to be done properly anyway for the set of use cases which do need it + +## Decision + +The latest **DRAFT** proposal is: + +1. we are alignment on adopting [ADR 033](adr-033-protobuf-inter-module-comm.md) not just as an addition to the + framework, but as a core replacement to the keeper paradigm entirely. +2. the ADR 033 inter-module router will accommodate any variation of approach (A) or (B) given the following rules: + a. if the client type is the same as the server type then pass it directly through, + b. if both client and server use the zero-copy generated code wrappers (which still need to be defined), then pass + the memory buffers from one wrapper to the other, or + c. marshal/unmarshal types between client and server. + +This approach will allow for both maximal correctness and enable a clear path to enabling modules within in other +languages, possibly executed within a WASM VM. + +### Minor API Revisions + +To declare minor API revisions of proto files, we propose the following guidelines (which were already documented +in [cosmos.app.v1alpha module options](../proto/cosmos/app/v1alpha1/module.proto)): +* proto packages which are revised from their initial version (considered revision `0`) should include a `package` +* comment in some .proto file containing the test `Revision N` at the start of a comment line where `N` is the current +revision number. +* all fields, messages, etc. added in a version beyond the initial revision should add a comment at the start of a +comment line of the form `Since: Revision N` where `N` is the non-zero revision it was added. + +It is advised that there is a 1:1 correspondence between a state machine module and versioned set of proto files +which are versioned either as a buf module a go API module or both. If the buf schema registry is used, the version of +this buf module should always be `1.N` where `N` corresponds to the package revision. Patch releases should be used when +only documentation comments are updated. It is okay to include proto packages named `v2`, `v3`, etc. in this same +`1.N` versioned buf module (ex. `cosmos.bank.v2`) as long as all these proto packages consist of a single API intended +to be served by a single SDK module. + +### Introspecting Minor API Revisions + +In order for modules to introspect the minor API revision of peer modules, we propose adding the following method +to `cosmossdk.io/core/intermodule.Client`: + +```go +ServiceRevision(ctx context.Context, serviceName string) uint64 +``` + +Modules could all this using the service name statically generated by the go grpc code generator: + +```go +intermoduleClient.ServiceRevision(ctx, bankv1beta1.Msg_ServiceDesc.ServiceName) +``` + +In the future, we may decide to extend the code generator used for protobuf services to add a field +to client types which does this check more concisely, ex: + +```go +package bankv1beta1 + +type MsgClient interface { + Send(context.Context, MsgSend) (MsgSendResponse, error) + ServiceRevision(context.Context) uint64 +} +``` + +### Unknown Field Filtering + +To correctly perform [unknown field filtering](adr-020-protobuf-transaction-encoding.md#unknown-field-filtering), +the inter-module router can do one of the following: + +* use the `protoreflect` API for messages which support that +* for gogo proto messages, marshal and use the existing `codec/unknownproto` code +* for zero-copy messages, do a simple check on the highest set field number (assuming we can require that fields are + adding consecutively in increasing order) + +### `FileDescriptor` Registration + +Because a single go binary may contain different versions of the same generated protobuf code, we cannot rely on the +global protobuf registry to contain the correct `FileDescriptor`s. Because `appconfig` module configuration is itself +written in protobuf, we would like to load the `FileDescriptor`s for a module before loading a module itself. So we +will provide ways to register `FileDescriptor`s at module registration time before instantiation. We propose the +following `cosmossdk.io/core/appmodule.Option` constructors for the various cases of how `FileDescriptor`s may be +packaged: + +```go +package appmodule + +// this can be used when we are using google.golang.org/protobuf compatible generated code +// Ex: +// ProtoFiles(bankv1beta1.File_cosmos_bank_v1beta1_module_proto) +func ProtoFiles(file []protoreflect.FileDescriptor) Option {} + +// this can be used when we are using gogo proto generated code. +func GzippedProtoFiles(file [][]byte) Option {} + +// this can be used when we are using buf build to generated a pinned file descriptor +func ProtoImage(protoImage []byte) Option {} +``` + +This approach allows us to support several ways protobuf files might be generated: +* proto files generated internally to a module (use `ProtoFiles`) +* the API module approach with pinned file descriptors (use `ProtoImage`) +* gogo proto (use `GzippedProtoFiles`) + +### Module Dependency Declaration + +One risk of ADR 033 is that dependencies are called at runtime which are not present in the loaded set of SDK modules. +Also we want modules to have a way to define a minimum dependency API revision that they require. Therefore, all +modules should declare their set of dependencies upfront. These dependencies could be defined when a module is +instantiated, but ideally we know what the dependencies are before instantiation and can statically look at an app +config and determine whether the set of modules. For example, if `bar` requires `foo` revision `>= 1`, then we +should be able to know this when creating an app config with two versions of `bar` and `foo`. + +We propose defining these dependencies in the proto options of the module config object itself. + +### Interface Registration + +We will also need to define how interface methods are defined on types that are serialized as `google.protobuf.Any`'s. +In light of the desire to support modules in other languages, we may want to think of solutions that will accommodate +other languages such as plugins described briefly in [ADR 033](adr-033-protobuf-inter-module-comm.md#internal-methods). + +### Testing + +In order to ensure that modules are indeed with multiple versions of their dependencies, we plan to provide specialized +unit and integration testing infrastructure that automatically tests multiple versions of dependencies. + +#### Unit Testing + +Unit tests should be conducted inside SDK modules by mocking their dependencies. In a full ADR 033 scenario, +this means that all interaction with other modules is done via the inter-module router, so mocking of dependencies +means mocking their msg and query server implementations. We will provide both a test runner and fixture to make this +streamlined. The key thing that the test runner should do to test compatibility is to test all combinations of +dependency API revisions. This can be done by taking the file descriptors for the dependencies, parsing their comments +to determine the revisions various elements were added, and then created synthetic file descriptors for each revision +by subtracting elements that were added later. + +Here is a proposed API for the unit test runner and fixture: + +```go +package moduletesting + +import ( + "context" + "testing" + + "cosmossdk.io/core/intermodule" + "cosmossdk.io/depinject" + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protodesc" +) + +type TestFixture interface { + context.Context + intermodule.Client // for making calls to the module we're testing + BeginBlock() + EndBlock() +} + +type UnitTestFixture interface { + TestFixture + grpc.ServiceRegistrar // for registering mock service implementations +} + +type UnitTestConfig struct { + ModuleConfig proto.Message // the module's config object + DepinjectConfig depinject.Config // optional additional depinject config options + DependencyFileDescriptors []protodesc.FileDescriptorProto // optional dependency file descriptors to use instead of the global registry +} + +// Run runs the test function for all combinations of dependency API revisions. +func (cfg UnitTestConfig) Run(t *testing.T, f func(t *testing.T, f UnitTestFixture)) { + // ... +} +``` + +Here is an example for testing bar calling foo which takes advantage of conditional service revisions in the expected +mock arguments: + +```go +func TestBar(t *testing.T) { + UnitTestConfig{ModuleConfig: &foomodulev1.Module{}}.Run(t, func (t *testing.T, f moduletesting.UnitTestFixture) { + ctrl := gomock.NewController(t) + mockFooMsgServer := footestutil.NewMockMsgServer() + foov1.RegisterMsgServer(f, mockFooMsgServer) + barMsgClient := barv1.NewMsgClient(f) + if f.ServiceRevision(foov1.Msg_ServiceDesc.ServiceName) >= 1 { + mockFooMsgServer.EXPECT().DoSomething(gomock.Any(), &foov1.MsgDoSomething{ + ..., + Condition: ..., // condition is expected in revision >= 1 + }).Return(&foov1.MsgDoSomethingResponse{}, nil) + } else { + mockFooMsgServer.EXPECT().DoSomething(gomock.Any(), &foov1.MsgDoSomething{...}).Return(&foov1.MsgDoSomethingResponse{}, nil) + } + res, err := barMsgClient.CallFoo(f, &MsgCallFoo{}) + ... + }) +} +``` + +The unit test runner would make sure that no dependency mocks return arguments which are invalid for the service +revision being tested to ensure that modules don't incorrectly depend on functionality not present in a given revision. + +#### Integration Testing + +An integration test runner and fixture would also be provided which instead of using mocks would test actual module +dependencies in various combinations. Here is the proposed API: + +```go +type IntegrationTestFixture interface { + TestFixture +} + +type IntegrationTestConfig struct { + ModuleConfig proto.Message // the module's config object + DependencyMatrix map[string][]proto.Message // all the dependent module configs +} + +// Run runs the test function for all combinations of dependency modules. +func (cfg IntegationTestConfig) Run(t *testing.T, f func (t *testing.T, f IntegrationTestFixture)) { + // ... +} +``` + +And here is an example with foo and bar: + +```go +func TestBarIntegration(t *testing.T) { + IntegrationTestConfig{ + ModuleConfig: &barmodulev1.Module{}, + DependencyMatrix: map[string][]proto.Message{ + "runtime": []proto.Message{ // test against two versions of runtime + &runtimev1.Module{}, + &runtimev2.Module{}, + }, + "foo": []proto.Message{ // test against three versions of foo + &foomodulev1.Module{}, + &foomodulev2.Module{}, + &foomodulev3.Module{}, + } + } + }.Run(t, func (t *testing.T, f moduletesting.IntegrationTestFixture) { + barMsgClient := barv1.NewMsgClient(f) + res, err := barMsgClient.CallFoo(f, &MsgCallFoo{}) + ... + }) +} +``` + +Unlike unit tests, integration tests actually pull in other module dependencies. So that modules can be written +without direct dependencies on other modules and because golang has no concept of development dependencies, integration +tests should be written in separate go modules, ex. `example.com/bar/v2/test`. Because this paradigm uses go semantic +versioning, it is possible to build a single go module which imports 3 versions of bar and 2 versions of runtime and +can test these all together in the six various combinations of dependencies. + +## Consequences + +### Backwards Compatibility + +Modules which migrate fully to ADR 033 will not be compatible with existing modules which use the keeper paradigm. +As a temporary workaround we may create some wrapper types that emulate the current keeper interface to minimize +the migration overhead. + +### Positive + +* we will be able to deliver interoperable semantically versioned modules which should dramatically increase the + ability of the Cosmos SDK ecosystem to iterate on new features +* it will be possible to write Cosmos SDK modules in other languages in the near future + +### Negative + +* all modules will need to be refactored somewhat dramatically + +### Neutral + +* the `cosmossdk.io/core/appconfig` framework will play a more central role in terms of how modules are defined, this + is likely generally a good thing but does mean additional changes for users wanting to stick to the pre-depinject way + of wiring up modules +* `depinject` is somewhat less needed or maybe even obviated because of the full ADR 033 approach. If we adopt the + core API proposed in https://github.com/cosmos/cosmos-sdk/pull/12239, then a module would probably always instantiate + itself with a method `ProvideModule(appmodule.Service) (appmodule.AppModule, error)`. There is no complex wiring of + keeper dependencies in this scenario and dependency injection may not have as much of (or any) use case. + +## Further Discussions + +The decision described above is considered in draft mode and is pending final buy-in from the team and key stakeholders. +Key outstanding discussions if we do adopt that direction are: + +* how do module clients introspect dependency module API revisions +* how do modules determine a minor dependency module API revision requirement +* how do modules appropriately test compatibility with different dependency versions +* how to register and resolve interface implementations +* how do modules register their protobuf file descriptors depending on the approach they take to generated code (the + API module approach may still be viable as a supported strategy and would need pinned file descriptors) + +## References + +* https://github.com/cosmos/cosmos-sdk/discussions/10162 +* https://github.com/cosmos/cosmos-sdk/discussions/10582 +* https://github.com/cosmos/cosmos-sdk/discussions/10368 +* https://github.com/cosmos/cosmos-sdk/pull/11340 +* https://github.com/cosmos/cosmos-sdk/issues/11899 +* [ADR 020](adr-020-protobuf-transaction-encoding.md) +* [ADR 033](adr-033-protobuf-inter-module-comm.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-055-orm.md b/versioned_docs/version-0.47/integrate/architecture/adr-055-orm.md index 71a759526..be7255f09 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-055-orm.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-055-orm.md @@ -38,6 +38,7 @@ and https://github.com/cosmos/cosmos-sdk/pull/10454. These prior efforts culminated in the creation of the Cosmos SDK `orm` go module which uses protobuf annotations for specifying ORM table definitions. This ORM is based on the new `google.golang.org/protobuf/reflect/protoreflect` API and supports: + * sorted indexes for all simple protobuf types (except `bytes`, `enum`, `float`, `double`) as well as `Timestamp` and `Duration` * unsorted `bytes` and `enum` indexes * composite primary and secondary keys @@ -63,9 +64,9 @@ A code generator is included with the ORM which creates type safe wrappers aroun implementation and is the recommended way for modules to use the ORM. The ORM tests provide a simplified bank module demonstration which illustrates: -- [ORM proto options](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/internal/testpb/bank.proto) -- [Generated Code](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/internal/testpb/bank.cosmos_orm.go) -- [Example Usage in a Module Keeper](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/model/ormdb/module_test.go) +* [ORM proto options](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/internal/testpb/bank.proto) +* [Generated Code](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/internal/testpb/bank.cosmos_orm.go) +* [Example Usage in a Module Keeper](https://github.com/cosmos/cosmos-sdk/blob/0d846ae2f0424b2eb640f6679a703b52d407813d/orm/model/ormdb/module_test.go) ## Consequences @@ -92,12 +93,13 @@ for potential improvements ## Further Discussions Further discussions will happen within the Cosmos SDK Framework Working Group. Current planned and ongoing work includes: + * automatically generate client-facing query layer * client-side query libraries that transparently verify light client proofs * index ORM data to SQL databases * improve performance by: - * optimizing existing reflection based code to avoid unnecessary gets when doing deletes & updates of simple tables - * more sophisticated code generation such as making fast path reflection even faster (avoiding `switch` statements), + * optimizing existing reflection based code to avoid unnecessary gets when doing deletes & updates of simple tables + * more sophisticated code generation such as making fast path reflection even faster (avoiding `switch` statements), or even fully generating code that equals handwritten performance @@ -108,4 +110,4 @@ Further discussions will happen within the Cosmos SDK Framework Working Group. C * https://github.com/cosmos/cosmos-sdk/tree/35d3312c3be306591fcba39892223f1244c8d108/x/group/internal/orm * https://github.com/cosmos/cosmos-sdk/discussions/9156 * https://github.com/allinbits/cosmos-sdk-poc/tree/master/runtime/orm -* https://github.com/cosmos/cosmos-sdk/pull/10454 \ No newline at end of file +* https://github.com/cosmos/cosmos-sdk/pull/10454 diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-057-app-wiring.md b/versioned_docs/version-0.47/integrate/architecture/adr-057-app-wiring.md index 341aec9f0..0a23f3933 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-057-app-wiring.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-057-app-wiring.md @@ -22,13 +22,13 @@ which contains almost 100 lines of imports and is otherwise over 600 lines of mo generally copied to each new project. (Not to mention the additional boilerplate which gets copied in `simapp/simd`.) The large amount of boilerplate needed to bootstrap an app has made it hard to release independently versioned go -modules for Cosmos SDK modules as described in [ADR 053: Go Module Refactoring](./adr-053-go-module-refactoring.md). +modules for Cosmos SDK modules as described in [ADR 053: Go Module Refactoring](adr-053-go-module-refactoring.md). In addition to being very verbose and repetitive, `app.go` also exposes a large surface area for breaking changes as most modules instantiate themselves with positional parameters which forces breaking changes anytime a new parameter (even an optional one) is needed. -Several attempts were made to improve the current situation including [ADR 033: Internal-Module Communication](./adr-033-protobuf-inter-module-comm.md) +Several attempts were made to improve the current situation including [ADR 033: Internal-Module Communication](adr-033-protobuf-inter-module-comm.md) and [a proof-of-concept of a new SDK](https://github.com/allinbits/cosmos-sdk-poc). The discussions around these designs led to the current solution described here. @@ -215,6 +215,9 @@ can help us figure out issues with missing dependencies in an app config if the In cases where required modules are not loaded at runtime, it may be possible to guide users to the correct module if through a global Cosmos SDK module registry. +The `*appmodule.Handler` type referenced above is a replacement for the legacy `AppModule` framework, and +described in [ADR 063: Core Module API](./adr-063-core-module-api.md). + ### New `app.go` With this setup, `app.go` might now look something like this: @@ -242,8 +245,10 @@ func main() { ### Application to existing SDK modules So far we have described a system which is largely agnostic to the specifics of the SDK such as store keys, `AppModule`, -`BaseApp`, etc. A second app wiring ADR will be created which outlines the details of how this app wiring system will -be applied to the existing SDK in a way that: +`BaseApp`, etc. Improvements to these parts of the framework that integrate with the general app wiring framework +defined here are described in [ADR 061: Core Module API](./adr-063-core-module-api.md). + +### Registration of Inter-Module Hooks ### Registration of Inter-Module Hooks @@ -252,6 +257,7 @@ when certain events happen. With the app wiring framework, these hooks interfaces can be defined as a `OnePerModuleType`s and then the module which consumes these hooks can collect these hooks as a map of module name to hook type (ex. `map[string]FooHooks`). Ex: + ```go func init() { appmodule.Register( @@ -275,6 +281,7 @@ in its config object. An alternative way for registering hooks via reflection was considered where all keeper types are inspected to see if they implement the hook interface by the modules exposing hooks. This has the downsides of: + * needing to expose all the keepers of all modules to the module providing hooks, * not allowing for encapsulating hooks on a different type which doesn't expose all keeper methods, * harder to know statically which module expose hooks or are checking for them. @@ -286,6 +293,7 @@ With the approach proposed here, hooks registration will be obviously observable The `depinject` framework will optionally allow the app configuration and dependency injection wiring to be code generated. This will allow: + * dependency injection wiring to be inspected as regular go code just like the existing `app.go`, * dependency injection to be opt-in with manual wiring 100% still possible. @@ -329,3 +337,4 @@ light of code generation. It may be better to do this type registration with a D * https://github.com/google/wire * https://pkg.go.dev/github.com/cosmos/cosmos-sdk/container * https://github.com/cosmos/cosmos-sdk/pull/11802 +* [ADR 063](./adr-063-core-module-api.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-058-auto-generated-cli.md b/versioned_docs/version-0.47/integrate/architecture/adr-058-auto-generated-cli.md index 1301466e1..b295ff4b2 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-058-auto-generated-cli.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-058-auto-generated-cli.md @@ -42,6 +42,7 @@ The basic design for automatically generating CLI commands is to: In order to make the auto-generated CLI as easy to use (or easier) than handwritten CLI, we need to do custom handling of specific protobuf field types so that the input format is easy for humans: + * `Coin`, `Coins`, `DecCoin`, and `DecCoins` should be input using the existing format (i.e. `1000uatom`) * it should be possible to specify an address using either the bech32 address string or a named key in the keyring * `Timestamp` and `Duration` should accept strings like `2001-01-01T00:00:00Z` and `1h3m` respectively @@ -74,12 +75,14 @@ this functionality. ## Further Discussions We would like to be able to customize: + * short and long usage strings for commands * aliases for flags (ex. `-a` for `--amount`) * which fields are positional parameters rather than flags It is an [open discussion](https://github.com/cosmos/cosmos-sdk/pull/11725#issuecomment-1108676129) as to whether these customizations options should line in: + * the .proto files themselves, * separate config files (ex. YAML), or * directly in code diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-059-test-scopes.md b/versioned_docs/version-0.47/integrate/architecture/adr-059-test-scopes.md index 51f06621c..060344593 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-059-test-scopes.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-059-test-scopes.md @@ -3,6 +3,8 @@ ## Changelog * 2022-08-02: Initial Draft +* 2023-03-02: Add precision for integration tests +* 2023-03-23: Add precision for E2E tests ## Status @@ -55,13 +57,11 @@ These are almost like integration tests in that they exercise many things togeth use mocks. Example 1 journey vs illustrative tests - [depinject's BDD style tests](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/features/bindings.feature), show how we can -rapidly build up many illustrative cases demonstrating behavioral rules without [very much -code](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/binding_test.go) while maintaining high level readability. +rapidly build up many illustrative cases demonstrating behavioral rules without [very much code](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/binding_test.go) while maintaining high level readability. Example 2 [depinject table driven tests](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/provider_desc_test.go) -Example 3 [Bank keeper tests](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/bank/keeper/keeper_test.go#L94-L105) - A mock implementation of `AccountKeeper` is -supplied to the keeper constructor. +Example 3 [Bank keeper tests](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/bank/keeper/keeper_test.go#L94-L105) - A mock implementation of `AccountKeeper` is supplied to the keeper constructor. #### Limitations @@ -127,7 +127,6 @@ gap in current simulation test coverage. Modules not returning simulation operations: * `auth` -* `capability` * `evidence` * `mint` * `params` @@ -148,6 +147,9 @@ End to end tests exercise the entire system as we understand it in as close an a to a production environment as is practical. Presently these tests are located at [tests/e2e](https://github.com/cosmos/cosmos-sdk/tree/main/tests/e2e) and rely on [testutil/network](https://github.com/cosmos/cosmos-sdk/tree/main/testutil/network) to start up an in-process Tendermint node. +An application should be built as minimally as possible to exercise the desired functionality. +The SDK uses an application will only the required modules for the tests. The application developer is adviced to use its own application for e2e tests. + #### Limitations In general the limitations of end to end tests are orchestration and compute cost. @@ -163,12 +165,14 @@ The scope of e2e tests has been complected with command line interface testing. We accept these test scopes and identify the following decisions points for each. -| Scope | App Fixture | Mocks? | -| ----------- | ----------- | ------ | -| Unit | None | Yes | -| Integration | depinject | Some | -| Simulation | depinject | No | -| E2E | simapp | No | +| Scope | App Type | Mocks? | +| ----------- | ------------------- | ------ | +| Unit | None | Yes | +| Integration | integration helpers | Some | +| Simulation | minimal app | No | +| E2E | minimal app | No | + +The decision above is valid for the SDK. An application developer should test their application with their full application instead of the minimal app. ### Unit Tests @@ -176,8 +180,6 @@ All modules must have mocked unit test coverage. Illustrative tests should outnumber journeys in unit tests. -~BDD feature tests are recommended when building up illustrative and journey scenarios.~ - Unit tests should outnumber integration tests. Unit tests must not introduce additional dependencies beyond those already present in @@ -201,7 +203,7 @@ Integration tests should outnumber e2e tests. ### Simulations -Simulations shall use `depinject`. They are located under `/x/{moduleName}/simulation`. +Simulations shall use a minimal application (usually via app wiring). They are located under `/x/{moduleName}/simulation`. ### E2E Tests @@ -234,7 +236,6 @@ demonstrated in [PR#12706](https://github.com/cosmos/cosmos-sdk/pull/12706). ### Neutral -* learning curve for BDD style tests * some discovery required for e2e transition to dockertest ## Further Discussions diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-060-abci-1.0.md b/versioned_docs/version-0.47/integrate/architecture/adr-060-abci-1.0.md index d988f7d50..3f29be784 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-060-abci-1.0.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-060-abci-1.0.md @@ -1,12 +1,14 @@ -# ADR 60: ABCI 1.0 Integration +# ADR 60: ABCI 1.0 Integration (Phase I) ## Changelog * 2022-08-10: Initial Draft (@alexanderbez, @tac0turtle) +* Nov 12, 2022: Update `PrepareProposal` and `ProcessProposal` semantics per the + initial implementation [PR](https://github.com/cosmos/cosmos-sdk/pull/13453) (@alexanderbez) ## Status -PROPOSED +ACCEPTED ## Abstract @@ -32,8 +34,14 @@ sends it, favoring its own transactions. This essentially means that the Tenderm mempool acts more like a gossip data structure. The second ABCI method, `ProcessProposal`, is used to process the block proposer's -proposal as defined by `PrepareProposal`. This ABCI method requests that the -application evaluate the entire proposed block for validity. +proposal as defined by `PrepareProposal`. It is important to note the following +with respect to `ProcessProposal`: + +* Execution of `ProcessProposal` must be deterministic. +* There must be coherence between `PrepareProposal` and `ProcessProposal`. In + other words, for any two correct processes *p* and *q*, if *q*'s Tendermint + calls `RequestProcessProposal` on *up*, *q*'s Application returns + ACCEPT in `ResponseProcessProposal`. It is important to note that in ABCI 1.0 integration, the application is NOT responsible for locking semantics -- Tendermint will still be responsible @@ -44,8 +52,8 @@ which allows for parallel execution possibilities. We will integrate ABCI 1.0, which will be introduced in Tendermint v0.37.0, in the next major release of the Cosmos SDK. We will integrate ABCI 1.0 -methods on the `BaseApp` type. We describe the implementations -of the two methods individually below. +methods on the `BaseApp` type. We describe the implementations of the two methods +individually below. Prior to describing the implementation of the two new methods, it is important to note that the existing ABCI methods, `CheckTx`, `DeliverTx`, etc, still exist and @@ -56,7 +64,7 @@ serve the same functions as they do now. Prior to evaluating the decision for how to implement `PrepareProposal`, it is important to note that `CheckTx` will still be executed and will be responsible for evaluating transaction validity as it does now, with one very important -_additive_ distinction. +*additive* distinction. When executing transactions in `CheckTx`, the application will now add valid transactions, i.e. passing the AnteHandler, to its own mempool data structure. @@ -69,82 +77,52 @@ custom mempool implementation. We define the general mempool interface as follows (subject to change): ```go -// MempoolTx we define an app-side mempool transaction interface that is as -// minimal as possible, only requiring applications to define the size of the -// transaction to be used when reaping and getting the transaction itself. -// Interface type casting can be used in the actual app-side mempool implementation. -type MempoolTx interface { - // Size returns the size of the transaction in bytes. - Size(codec.Codec) int - Tx() sdk.Tx -} +type Mempool interface { + // Insert attempts to insert a Tx into the app-side mempool returning + // an error upon failure. + Insert(sdk.Context, sdk.Tx) error -// PrepareTxRecord defines a wrapper around a MempoolTx that is returned from -// PrepareProposal which includes an Action to inform Tendermint what to do with -// the transaction. -type PrepareTxRecord[T MempoolTx] struct { - Tx T - Action abci.TxAction -} + // Select returns an Iterator over the app-side mempool. If txs are specified, + // then they shall be incorporated into the Iterator. The Iterator must + // closed by the caller. + Select(sdk.Context, [][]byte) Iterator + + // CountTx returns the number of transactions currently in the mempool. + CountTx() int -type Mempool[T MempoolTx] interface { - // Insert attempts to insert a MempoolTx into the app-side mempool returning - // an error upon failure. - Insert(sdk.Context, T) error - // ReapMaxBytes returns the next set of available transactions from the app-side - // mempool, up to maxBytes or until the mempool is empty. The application can - // decide to return transactions from its own mempool or from the incoming - // TxRecords or some combination of both. The notion of 'available' or 'next' - // is defined by the application's mempool implementation. - ReapMaxBytes(ctx sdk.Context, txRecords abci.TxRecords, maxBytes int) ([]PrepareTxRecord[T], error) - // NumTxs returns the number of transactions currently in the mempool. - NumTxs() int // Remove attempts to remove a transaction from the mempool, returning an error // upon failure. - Remove(sdk.Context, T) error + Remove(sdk.Tx) error } -``` -We will define an implementation of `Mempool[T MempoolTx]` that will cover a -majority of application use cases. Namely, it will prioritize transactions by -priority and transaction sender, allowing for multiple prioritized transactions -from the same sender. The app-side mempool will be defined as a wrapper around a -simple priority queue using a max binary heap, along with additional indexes/metadata -to store senders and their nonces, allowing for simple multi-dimensional -prioritization (2-ary). - -Transaction reaping will essentially happen via a two-phase approach: - -1. Reap one or more transactions from the priority queue and collect them into - one of two buffers -- _valid_ and _invalid_. -2. For transactions that DO NOT violate the nonce validation, they are included - in the _valid_ buffer. -3. For transactions that DO violate the nonce validation, they are included in - the _invalid_ buffer. -4. Continue this process until the desired number of valid transactions are - reaped or until the mempool is empty. -5. Provide Tendermint the list of all transactions from the _valid_ buffer. -6. Re-insert all transactions, from both buffers, back into app-side mempool. - This is to ensure we do not discard transactions from the app-side mempool in - case `ProcessProposal` fails or in case that the proposal, while passing - `ProcessProposal` is not the one decided for that height, i.e. the height took - more than one round. +// Iterator defines an app-side mempool iterator interface that is as minimal as +// possible. The order of iteration is determined by the app-side mempool +// implementation. +type Iterator interface { + // Next returns the next transaction from the mempool. If there are no more + // transactions, it returns nil. + Next() Iterator -```go -type PriorityMempool[T MempoolTx] struct { - queue *PriorityQueue[MempoolTx] + // Tx returns the transaction at the current position of the iterator. + Tx() sdk.Tx +} +``` + +We will define an implementation of `Mempool`, defined by `nonceMempool`, that +will cover most basic application use-cases. Namely, it will prioritize transactions +by transaction sender, allowing for multiple transactions from the same sender. - // senders will contain a mapping from tx sender account addresses to all - // sequence numbers (nonces) or txs that they have in the app-side mempool. - senders map[string][]int64 +The default app-side mempool implementation, `nonceMempool`, will operate on a +single skip list data structure. Specifically, transactions with the lowest nonce +globally are prioritized. Transactions with the same nonce are prioritized by +sender address. - // ... +```go +type nonceMempool struct { + txQueue *huandu.SkipList } ``` -> The `PriorityMempool[T MempoolTx]` implementation will support Options such as -> limiting the mempool size by a fixed number of bytes. - Previous discussions1 have come to the agreement that Tendermint will perform a request to the application, via `RequestPrepareProposal`, with a certain amount of transactions reaped from Tendermint's local mempool. The exact amount @@ -154,13 +132,24 @@ This is referred to as the "one-shot approach" seen in discussions. When Tendermint reaps transactions from the local mempool and sends them to the application via `RequestPrepareProposal`, the application will have to evaluate the transactions. Specifically, it will need to inform Tendermint if it should -reject and or include each transaction. Note, the application can even _replace_ +reject and or include each transaction. Note, the application can even *replace* transactions entirely with other transactions. When evaluating transactions from `RequestPrepareProposal`, the application will -ignore _all_ transactions sent to it in the request and instead reap up to -`RequestPrepareProposal.max_tx_bytes` from it's own mempool. There is no need to -execute the transactions for validity as they have already passed CheckTx. +ignore *ALL* transactions sent to it in the request and instead reap up to +`RequestPrepareProposal.max_tx_bytes` from it's own mempool. + +Since an application can technically insert or inject transactions on `Insert` +during `CheckTx` execution, it is recommended that applications ensure transaction +validity when reaping transactions during `PrepareProposal`. However, what validity +exactly means is entirely determined by the application. + +The Cosmos SDK will provide a default `PrepareProposal` implementation that simply +select up to `MaxBytes` *valid* transactions. + +However, applications can override this default implementation with their own +implementation and set that on `BaseApp` via `SetPrepareProposal`. + ### `ProcessProposal` @@ -190,9 +179,9 @@ Note, we must call `ProcessProposal` with a new internal branched state on the off of `deliverState`. Note, the `processProposalState` is never committed and is completely discarded after `ProcessProposal` finishes execution. -We will only populate the `Status` field of the `ResponseProcessProposal` with -`ACCEPT` if ALL the transactions were accepted as valid, otherwise we will -populate with `REJECT`. +The Cosmos SDK will provide a default implementation of `ProcessProposal` in which +all transactions are validated using the CheckTx flow, i.e. the AnteHandler, and +will always return ACCEPT unless any transaction cannot be decoded. ### `DeliverTx` diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-061-liquid-staking.md b/versioned_docs/version-0.47/integrate/architecture/adr-061-liquid-staking.md index 56e3f9b0c..fcfeda0d3 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-061-liquid-staking.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-061-liquid-staking.md @@ -6,7 +6,7 @@ ## Status -PROPOSED +ACCEPTED ## Abstract @@ -34,7 +34,7 @@ A new governance parameter is introduced that defines the ratio of exempt to iss Min self delegation is removed from the staking system with the expectation that it will be replaced by the exempt delegations system. The exempt delegation system allows multiple accounts to demonstrate economic alignment with the validator operator as team members, partners etc. without co-mingling funds. Delegation exemption will likely be required to grow the validators' business under widespread adoption of liquid staking once governance has adjusted the exemption factor. -When shares are tokenized, the underlying shares are transfered to a module account and rewards go to the module account for the TokenizedShareRecord. +When shares are tokenized, the underlying shares are transferred to a module account and rewards go to the module account for the TokenizedShareRecord. There is no longer a mechanism to override the validators vote for TokenizedShares. @@ -79,4 +79,4 @@ By setting the exemption factor to zero, this module works like legacy staking. ### Positive -This approach should enable integration with liquid staking providers and improved user experience. It provides a pathway to security under non-exponential issuance policies in the baseline staking module. \ No newline at end of file +This approach should enable integration with liquid staking providers and improved user experience. It provides a pathway to security under non-exponential issuance policies in the baseline staking module. diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-062-collections-state-layer.md b/versioned_docs/version-0.47/integrate/architecture/adr-062-collections-state-layer.md new file mode 100644 index 000000000..8ebaddda7 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/architecture/adr-062-collections-state-layer.md @@ -0,0 +1,117 @@ +# ADR 062: Collections, a simplified storage layer for cosmos-sdk modules. + +## Changelog + +* 30/11/2022: PROPOSED + +## Status + +PROPOSED - Implemented + +## Abstract + +We propose a simplified module storage layer which leverages golang generics to allow module developers to handle module +storage in a simple and straightforward manner, whilst offering safety, extensibility and standardisation. + +## Context + +Module developers are forced into manually implementing storage functionalities in their modules, those functionalities include +but are not limited to: + +- Defining key to bytes formats. +- Defining value to bytes formats. +- Defining secondary indexes. +- Defining query methods to expose outside to deal with storage. +- Defining local methods to deal with storage writing. +- Dealing with genesis imports and exports. +- Writing tests for all the above. + + +This brings in a lot of problems: +- It blocks developers from focusing on the most important part: writing business logic. +- Key to bytes formats are complex and their definition is error-prone, for example: + - how do I format time to bytes in such a way that bytes are sorted? + - how do I ensure when I don't have namespace collisions when dealing with secondary indexes? +- The lack of standardisation makes life hard for clients, and the problem is exacerbated when it comes to providing proofs for objects present in state. Clients are forced to maintain a list of object paths to gather proofs. + +### Current Solution: ORM + +The current SDK proposed solution to this problem is [ORM](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-055-orm.md). +Whilst ORM offers a lot of good functionality aimed at solving these specific problems, it has some downsides: +- It requires migrations. +- It uses the newest protobuf golang API, whilst the SDK still mainly uses gogoproto. +- Integrating ORM into a module would require the developer to deal with two different golang frameworks (golang protobuf + gogoproto) representing the same API objects. +- It has a high learning curve, even for simple storage layers as it requires developers to have knowledge around protobuf options, custom cosmos-sdk storage extensions, and tooling download. Then after this they still need to learn the code-generated API. + +### CosmWasm Solution: cw-storage-plus + +The collections API takes inspiration from [cw-storage-plus](https://docs.cosmwasm.com/docs/1.0/smart-contracts/state/cw-plus/), +which has demonstrated to be a powerful tool for dealing with storage in CosmWasm contracts. +It's simple, does not require extra tooling, it makes it easy to deal with complex storage structures (indexes, snapshot, etc). +The API is straightforward and explicit. + +## Decision + +We propose to port the `collections` API, whose implementation lives in [NibiruChain/collections](https://github.com/NibiruChain/collections) to cosmos-sdk. + +Collections implements four different storage handlers types: + +- `Map`: which deals with simple `key=>object` mappings. +- `KeySet`: which acts as a `Set` and only retains keys and no object (usecase: allow-lists). +- `Item`: which always contains only one object (usecase: Params) +- `Sequence`: which implements a simple always increasing number (usecase: Nonces) +- `IndexedMap`: builds on top of `Map` and `KeySet` and allows to create relationships with `Objects` and `Objects` secondary keys. + +All the collection APIs build on top of the simple `Map` type. + +Collections is fully generic, meaning that anything can be used as `Key` and `Value`. It can be a protobuf object or not. + +Collections types, in fact, delegate the duty of serialisation of keys and values to a secondary collections API component called `ValueEncoders` and `KeyEncoders`. + +`ValueEncoders` take care of converting a value to bytes (relevant only for `Map`). And offers a plug and play layer which allows us to change how we encode objects, +which is relevant for swapping serialisation frameworks and enhancing performance. +`Collections` already comes in with default `ValueEncoders`, specifically for: protobuf objects, special SDK types (sdk.Int, sdk.Dec). + +`KeyEncoders` take care of converting keys to bytes, `collections` already comes in with some default `KeyEncoders` for some privimite golang types +(uint64, string, time.Time, ...) and some widely used sdk types (sdk.Acc/Val/ConsAddress, sdk.Int/Dec, ...). +These default implementations also offer safety around proper lexicographic ordering and namespace-collision. + +Examples of the collections API can be found here: +- introduction: https://github.com/NibiruChain/collections/tree/main/examples +- usage in nibiru: [x/oracle](https://github.com/NibiruChain/nibiru/blob/master/x/oracle/keeper/keeper.go#L32), [x/perp](https://github.com/NibiruChain/nibiru/blob/master/x/perp/keeper/keeper.go#L31) +- cosmos-sdk's x/staking migrated: https://github.com/testinginprod/cosmos-sdk/pull/22 + + +## Consequences + +### Backwards Compatibility + +The design of `ValueEncoders` and `KeyEncoders` allows modules to retain the same `byte(key)=>byte(value)` mappings, making +the upgrade to the new storage layer non-state breaking. + + +### Positive + +- ADR aimed at removing code from the SDK rather than adding it. Migrating just `x/staking` to collections would yield to a net decrease in LOC (even considering the addition of collections itself). +- Simplifies and standardises storage layers across modules in the SDK. +- Does not require to have to deal with protobuf. +- It's pure golang code. +- Generalisation over `KeyEncoders` and `ValueEncoders` allows us to not tie ourself to the data serialisation framework. +- `KeyEncoders` and `ValueEncoders` can be extended to provide schema reflection. + +### Negative + +- Golang generics are not as battle-tested as other Golang features, despite being used in production right now. +- Collection types instantiation needs to be improved. + +### Neutral + +{neutral consequences} + +## Further Discussions + +- Automatic genesis import/export (not implemented because of API breakage) +- Schema reflection + + +## References diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-063-core-module-api.md b/versioned_docs/version-0.47/integrate/architecture/adr-063-core-module-api.md new file mode 100644 index 000000000..034b01fab --- /dev/null +++ b/versioned_docs/version-0.47/integrate/architecture/adr-063-core-module-api.md @@ -0,0 +1,507 @@ +# ADR 063: Core Module API + +## Changelog + +* 2022-08-18 First Draft +* 2022-12-08 First Draft +* 2023-01-24 Updates + +## Status + +ACCEPTED Partially Implemented + +## Abstract + +A new core API is proposed as a way to develop cosmos-sdk applications that will eventually replace the existing +`AppModule` and `sdk.Context` frameworks a set of core services and extension interfaces. This core API aims to: + +* be simpler +* more extensible +* more stable than the current framework +* enable deterministic events and queries, +* support event listeners +* [ADR 033: Protobuf-based Inter-Module Communication](adr-033-protobuf-inter-module-comm.md) clients. + +## Context + +Historically modules have exposed their functionality to the framework via the `AppModule` and `AppModuleBasic` +interfaces which have the following shortcomings: + +* both `AppModule` and `AppModuleBasic` need to be defined and registered which is counter-intuitive +* apps need to implement the full interfaces, even parts they don't need (although there are workarounds for this), +* interface methods depend heavily on unstable third party dependencies, in particular Comet, +* legacy required methods have littered these interfaces for far too long + +In order to interact with the state machine, modules have needed to do a combination of these things: + +* get store keys from the app +* call methods on `sdk.Context` which contains more or less the full set of capability available to modules. + +By isolating all the state machine functionality into `sdk.Context`, the set of functionalities available to +modules are tightly coupled to this type. If there are changes to upstream dependencies (such as Comet) +or new functionalities are desired (such as alternate store types), the changes need impact `sdk.Context` and all +consumers of it (basically all modules). Also, all modules now receive `context.Context` and need to convert these +to `sdk.Context`'s with a non-ergonomic unwrapping function. + +Any breaking changes to these interfaces, such as ones imposed by third-party dependencies like Comet, have the +side effect of forcing all modules in the ecosystem to update in lock-step. This means it is almost impossible to have +a version of the module which can be run with 2 or 3 different versions of the SDK or 2 or 3 different versions of +another module. This lock-step coupling slows down overall development within the ecosystem and causes updates to +components to be delayed longer than they would if things were more stable and loosely coupled. + +## Decision + +The `core` API proposes a set of core APIs that modules can rely on to interact with the state machine and expose their +functionalities to it that are designed in a principled way such that: + +* tight coupling of dependencies and unrelated functionalities is minimized or eliminated +* APIs can have long-term stability guarantees +* the SDK framework is extensible in a safe and straightforward way + +The design principles of the core API are as follows: + +* everything that a module wants to interact with in the state machine is a service +* all services coordinate state via `context.Context` and don't try to recreate the "bag of variables" approach of `sdk.Context` +* all independent services are isolated in independent packages with minimal APIs and minimal dependencies +* the core API should be minimalistic and designed for long-term support (LTS) +* a "runtime" module will implement all the "core services" defined by the core API and can handle all module + functionalities exposed by core extension interfaces +* other non-core and/or non-LTS services can be exposed by specific versions of runtime modules or other modules +following the same design principles, this includes functionality that interacts with specific non-stable versions of +third party dependencies such as Comet +* the core API doesn't implement *any* functionality, it just defines types +* go stable API compatibility guidelines are followed: https://go.dev/blog/module-compatibility + +A "runtime" module is any module which implements the core functionality of composing an ABCI app, which is currently +handled by `BaseApp` and the `ModuleManager`. Runtime modules which implement the core API are *intentionally* separate +from the core API in order to enable more parallel versions and forks of the runtime module than is possible with the +SDK's current tightly coupled `BaseApp` design while still allowing for a high degree of composability and +compatibility. + +Modules which are built only against the core API don't need to know anything about which version of runtime, +`BaseApp` or Comet in order to be compatible. Modules from the core mainline SDK could be easily composed +with a forked version of runtime with this pattern. + +This design is intended to enable matrices of compatible dependency versions. Ideally a given version of any module +is compatible with multiple versions of the runtime module and other compatible modules. This will allow dependencies +to be selectively updated based on battle-testing. More conservative projects may want to update some dependencies +slower than more fast moving projects. + +### Core Services + +The following "core services" are defined by the core API. All valid runtime module implementations should provide +implementations of these services to modules via both [dependency injection](adr-057-app-wiring.md) and +manual wiring. The individual services described below are all bundled in a convenient `appmodule.Service` +"bundle service" so that for simplicity modules can declare a dependency on a single service. + +#### Store Services + +Store services will be defined in the `cosmossdk.io/core/store` package. + +The generic `store.KVStore` interface is the same as current SDK `KVStore` interface. Store keys have been refactored +into store services which, instead of expecting the context to know about stores, invert the pattern and allow +retrieving a store from a generic context. There are three store services for the three types of currently supported +stores - regular kv-store, memory, and transient: + +```go +type KVStoreService interface { + OpenKVStore(context.Context) KVStore +} + +type MemoryStoreService interface { + OpenMemoryStore(context.Context) KVStore +} +type TransientStoreService interface { + OpenTransientStore(context.Context) KVStore +} +``` + +Modules can use these services like this: + +```go +func (k msgServer) Send(ctx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) { + store := k.kvStoreSvc.OpenKVStore(ctx) +} +``` + +Just as with the current runtime module implementation, modules will not need to explicitly name these store keys, +but rather the runtime module will choose an appropriate name for them and modules just need to request the +type of store they need in their dependency injection (or manual) constructors. + +#### Event Service + +The event `Service` will be defined in the `cosmossdk.io/core/event` package. + +The event `Service` allows modules to emit typed and legacy untyped events: + +```go +package event + +type Service interface { + // EmitProtoEvent emits events represented as a protobuf message (as described in ADR 032). + // + // Callers SHOULD assume that these events may be included in consensus. These events + // MUST be emitted deterministically and adding, removing or changing these events SHOULD + // be considered state-machine breaking. + EmitProtoEvent(ctx context.Context, event protoiface.MessageV1) error + + // EmitKVEvent emits an event based on an event and kv-pair attributes. + // + // These events will not be part of consensus and adding, removing or changing these events is + // not a state-machine breaking change. + EmitKVEvent(ctx context.Context, eventType string, attrs ...KVEventAttribute) error + + // EmitProtoEventNonConsensus emits events represented as a protobuf message (as described in ADR 032), without + // including it in blockchain consensus. + // + // These events will not be part of consensus and adding, removing or changing events is + // not a state-machine breaking change. + EmitProtoEventNonConsensus(ctx context.Context, event protoiface.MessageV1) error +} +``` + +Typed events emitted with `EmitProto` should be assumed to be part of blockchain consensus (whether they are part of +the block or app hash is left to the runtime to specify). + +Events emitted by `EmitKVEvent` and `EmitProtoEventNonConsensus` are not considered to be part of consensus and cannot be observed +by other modules. If there is a client-side need to add events in patch releases, these methods can be used. + +#### Logger + +A logger (`cosmossdk.io/log`) must be supplied using `depinject`, and will +be made available for modules to use via `depinject.In`. +Modules using it should follow the current pattern in the SDK by adding the module name before using it. + +```go +type ModuleInputs struct { + depinject.In + + Logger log.Logger +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + keeper := keeper.NewKeeper( + in.logger, + ) +} + +func NewKeeper(logger log.Logger) Keeper { + return Keeper{ + logger: logger.With(log.ModuleKey, "x/"+types.ModuleName), + } +} +``` + +``` + +### Core `AppModule` extension interfaces + + +Modules will provide their core services to the runtime module via extension interfaces built on top of the +`cosmossdk.io/core/appmodule.AppModule` tag interface. This tag interface requires only two empty methods which +allow `depinject` to identify implementors as `depinject.OnePerModule` types and as app module implementations: + +```go +type AppModule interface { + depinject.OnePerModuleType + + // IsAppModule is a dummy method to tag a struct as implementing an AppModule. + IsAppModule() +} +``` + +Other core extension interfaces will be defined in `cosmossdk.io/core` should be supported by valid runtime +implementations. + +#### `MsgServer` and `QueryServer` registration + +`MsgServer` and `QueryServer` registration is done by implementing the `HasServices` extension interface: + +```go +type HasServices interface { + AppModule + + RegisterServices(grpc.ServiceRegistrar) +} + +``` + +Because of the `cosmos.msg.v1.service` protobuf option, required for `Msg` services, the same `ServiceRegitrar` can be +used to register both `Msg` and query services. + +#### Genesis + +The genesis `Handler` functions - `DefaultGenesis`, `ValidateGenesis`, `InitGenesis` and `ExportGenesis` - are specified +against the `GenesisSource` and `GenesisTarget` interfaces which will abstract over genesis sources which may be a single +JSON object or collections of JSON objects that can be efficiently streamed. + +```go +// GenesisSource is a source for genesis data in JSON format. It may abstract over a +// single JSON object or separate files for each field in a JSON object that can +// be streamed over. Modules should open a separate io.ReadCloser for each field that +// is required. When fields represent arrays they can efficiently be streamed +// over. If there is no data for a field, this function should return nil, nil. It is +// important that the caller closes the reader when done with it. +type GenesisSource = func(field string) (io.ReadCloser, error) + +// GenesisTarget is a target for writing genesis data in JSON format. It may +// abstract over a single JSON object or JSON in separate files that can be +// streamed over. Modules should open a separate io.WriteCloser for each field +// and should prefer writing fields as arrays when possible to support efficient +// iteration. It is important the caller closers the writer AND checks the error +// when done with it. It is expected that a stream of JSON data is written +// to the writer. +type GenesisTarget = func(field string) (io.WriteCloser, error) +``` + +All genesis objects for a given module are expected to conform to the semantics of a JSON object. +Each field in the JSON object should be read and written separately to support streaming genesis. +The [ORM](adr-055-orm.md) and [collections](adr-062-collections-state-layer.md) both support +streaming genesis and modules using these frameworks generally do not need to write any manual +genesis code. + +To support genesis, modules should implement the `HasGenesis` extension interface: + +```go +type HasGenesis interface { + AppModule + + // DefaultGenesis writes the default genesis for this module to the target. + DefaultGenesis(GenesisTarget) error + + // ValidateGenesis validates the genesis data read from the source. + ValidateGenesis(GenesisSource) error + + // InitGenesis initializes module state from the genesis source. + InitGenesis(context.Context, GenesisSource) error + + // ExportGenesis exports module state to the genesis target. + ExportGenesis(context.Context, GenesisTarget) error +} +``` + +#### Begin and End Blockers + +Modules that have functionality that runs before transactions (begin blockers) or after transactions +(end blockers) should implement the has `HasBeginBlocker` and/or `HasEndBlocker` interfaces: + +```go +type HasBeginBlocker interface { + AppModule + BeginBlock(context.Context) error +} + +type HasEndBlocker interface { + AppModule + EndBlock(context.Context) error +} +``` + +The `BeginBlock` and `EndBlock` methods will take a `context.Context`, because: + +* most modules don't need Comet information other than `BlockInfo` so we can eliminate dependencies on specific +Comet versions +* for the few modules that need Comet block headers and/or return validator updates, specific versions of the +runtime module will provide specific functionality for interacting with the specific version(s) of Comet +supported + +In order for `BeginBlock`, `EndBlock` and `InitGenesis` to send back validator updates and retrieve full Comet +block headers, the runtime module for a specific version of Comet could provide services like this: + +```go +type ValidatorUpdateService interface { + SetValidatorUpdates(context.Context, []abci.ValidatorUpdate) +} +``` + +Header Service defines a way to get header information about a block. This information is generalized for all implementations: + +```go + +type Service interface { + GetHeaderInfo(context.Context) Info +} + +type Info struct { + Height int64 // Height returns the height of the block + Hash []byte // Hash returns the hash of the block header + Time time.Time // Time returns the time of the block + ChainID string // ChainId returns the chain ID of the block +} +``` + +Comet Service provides a way to get comet specific information: + +```go +type Service interface { + GetCometInfo(context.Context) Info +} + +type CometInfo struct { + Evidence []abci.Misbehavior // Misbehavior returns the misbehavior of the block + // ValidatorsHash returns the hash of the validators + // For Comet, it is the hash of the next validators + ValidatorsHash []byte + ProposerAddress []byte // ProposerAddress returns the address of the block proposer + DecidedLastCommit abci.CommitInfo // DecidedLastCommit returns the last commit info +} +``` + +If a user would like to provide a module other information they would need to implement another service like: + +```go +type RollKit Interface { + ... +} +``` + +We know these types will change at the Comet level and that also a very limited set of modules actually need this +functionality, so they are intentionally kept out of core to keep core limited to the necessary, minimal set of stable +APIs. + +#### Remaining Parts of AppModule + +The current `AppModule` framework handles a number of additional concerns which aren't addressed by this core API. +These include: + +* gas +* block headers +* upgrades +* registration of gogo proto and amino interface types +* cobra query and tx commands +* gRPC gateway +* crisis module invariants +* simulations + +Additional `AppModule` extension interfaces either inside or outside of core will need to be specified to handle +these concerns. + +In the case of gogo proto and amino interfaces, the registration of these generally should happen as early +as possible during initialization and in [ADR 057: App Wiring](./adr-057-app-wiring.md), protobuf type registration +happens before dependency injection (although this could alternatively be done dedicated DI providers). + +gRPC gateway registration should probably be handled by the runtime module, but the core API shouldn't depend on gRPC +gateway types as 1) we are already using an older version and 2) it's possible the framework can do this registration +automatically in the future. So for now, the runtime module should probably provide some sort of specific type for doing +this registration ex: + +```go +type GrpcGatewayInfo struct { + Handlers []GrpcGatewayHandler +} + +type GrpcGatewayHandler func(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error +``` + +which modules can return in a provider: + +```go +func ProvideGrpcGateway() GrpcGatewayInfo { + return GrpcGatewayinfo { + Handlers: []Handler {types.RegisterQueryHandlerClient} + } +} +``` + +Crisis module invariants and simulations are subject to potential redesign and should be managed with types +defined in the crisis and simulation modules respectively. + +Extension interface for CLI commands will be provided via the `cosmossdk.io/client/v2` module and its +[autocli](adr-058-auto-generated-cli.md) framework. + +#### Example Usage + +Here is an example of setting up a hypothetical `foo` v2 module which uses the [ORM](adr-055-orm.md) for its state +management and genesis. + +```go + +type Keeper struct { + db orm.ModuleDB + evtSrv event.Service +} + +func (k Keeper) RegisterServices(r grpc.ServiceRegistrar) { + foov1.RegisterMsgServer(r, k) + foov1.RegisterQueryServer(r, k) +} + +func (k Keeper) BeginBlock(context.Context) error { + return nil +} + +func ProvideApp(config *foomodulev2.Module, evtSvc event.EventService, db orm.ModuleDB) (Keeper, appmodule.AppModule){ + k := &Keeper{db: db, evtSvc: evtSvc} + return k, k +} +``` + +### Runtime Compatibility Version + +The `core` module will define a static integer var, `cosmossdk.io/core.RuntimeCompatibilityVersion`, which is +a minor version indicator of the core module that is accessible at runtime. Correct runtime module implementations +should check this compatibility version and return an error if the current `RuntimeCompatibilityVersion` is higher +than the version of the core API that this runtime version can support. When new features are adding to the `core` +module API that runtime modules are required to support, this version should be incremented. + +### Testing + +A mock implementation of all services should be provided in core to allow for unit testing of modules +without needing to depend on any particular version of runtime. Mock services should +allow tests to observe service behavior or provide a non-production implementation - for instance memory +stores can be used to mock stores. + +For integration testing, a mock runtime implementation should be provided that allows composing different app modules +together for testing without a dependency on runtime or Comet. + +## Consequences + +### Backwards Compatibility + +Early versions of runtime modules should aim to support as much as possible modules built with the existing +`AppModule`/`sdk.Context` framework. As the core API is more widely adopted, later runtime versions may choose to +drop support and only support the core API plus any runtime module specific APIs (like specific versions of Comet). + +The core module itself should strive to remain at the go semantic version `v1` as long as possible and follow design +principles that allow for strong long-term support (LTS). + +Older versions of the SDK can support modules built against core with adaptors that convert wrap core `AppModule` +implementations in implementations of `AppModule` that conform to that version of the SDK's semantics as well +as by providing service implementations by wrapping `sdk.Context`. + +### Positive + +* better API encapsulation and separation of concerns +* more stable APIs +* more framework extensibility +* deterministic events and queries +* event listeners +* inter-module msg and query execution support +* more explicit support for forking and merging of module versions (including runtime) + +### Negative + +### Neutral + +* modules will need to be refactored to use this API +* some replacements for `AppModule` functionality still need to be defined in follow-ups + (type registration, commands, invariants, simulations) and this will take additional design work + +## Further Discussions + +* gas +* block headers +* upgrades +* registration of gogo proto and amino interface types +* cobra query and tx commands +* gRPC gateway +* crisis module invariants +* simulations + +## References + +* [ADR 033: Protobuf-based Inter-Module Communication](adr-033-protobuf-inter-module-comm.md) +* [ADR 057: App Wiring](./adr-057-app-wiring.md) +* [ADR 055: ORM](adr-055-orm.md) +* [ADR 028: Public Key Addresses](adr-028-public-key-addresses.md) +* [Keeping Your Modules Compatible](https://go.dev/blog/module-compatibility) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-064-abci-2.0.md b/versioned_docs/version-0.47/integrate/architecture/adr-064-abci-2.0.md new file mode 100644 index 000000000..9a4718050 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/architecture/adr-064-abci-2.0.md @@ -0,0 +1,461 @@ +# ADR 64: ABCI 2.0 Integration (Phase II) + +## Changelog + +* 2023-01-17: Initial Draft (@alexanderbez) +* 2023-04-06: Add upgrading section (@alexanderbez) +* 2023-04-10: Simplify vote extension state persistence (@alexanderbez) + +## Status + +ACCEPTED + +## Abstract + +This ADR outlines the continuation of the efforts to implement ABCI++ in the Cosmos +SDK outlined in [ADR 060: ABCI 1.0 (Phase I)](adr-060-abci-1.0.md). + +Specifically, this ADR outlines the design and implementation of ABCI 2.0, which +includes `ExtendVote`, `VerifyVoteExtension` and `FinalizeBlock`. + +## Context + +ABCI 2.0 continues the promised updates from ABCI++, specifically three additional +ABCI methods that the application can implement in order to gain further control, +insight and customization of the consensus process, unlocking many novel use-cases +that previously not possible. We describe these three new methods below: + +### `ExtendVote` + +This method allows each validator process to extend the pre-commit phase of the +CometBFT consensus process. Specifically, it allows the application to perform +custom business logic that extends the pre-commit vote and supply additional data +as part of the vote, although they are signed separately by the same key. + +The data, called vote extension, will be broadcast and received together with the +vote it is extending, and will be made available to the application in the next +height. Specifically, the proposer of the next block will receive the vote extensions +in `RequestPrepareProposal.local_last_commit.votes`. + +If the application does not have vote extension information to provide, it +returns a 0-length byte array as its vote extension. + +**NOTE**: + +* Although each validator process submits its own vote extension, ONLY the *proposer* + of the *next* block will receive all the vote extensions included as part of the + pre-commit phase of the previous block. This means only the proposer will + implicitly have access to all the vote extensions, via `RequestPrepareProposal`, + and that not all vote extensions may be included, since a validator does not + have to wait for all pre-commits, only 2/3. +* The pre-commit vote is signed independently from the vote extension. + +### `VerifyVoteExtension` + +This method allows validators to validate the vote extension data attached to +each pre-commit message it receives. If the validation fails, the whole pre-commit +message will be deemed invalid and ignored by CometBFT. + +CometBFT uses `VerifyVoteExtension` when validating a pre-commit vote. Specifically, +for a pre-commit, CometBFT will: + +* Reject the message if it doesn't contain a signed vote AND a signed vote extension +* Reject the message if the vote's signature OR the vote extension's signature fails to verify +* Reject the message if `VerifyVoteExtension` was rejected by the app + +Otherwise, CometBFT will accept the pre-commit message. + +Note, this has important consequences on liveness, i.e., if vote extensions repeatedly +cannot be verified by correct validators, CometBFT may not be able to finalize +a block even if sufficiently many (+2/3) validators send pre-commit votes for +that block. Thus, `VerifyVoteExtension` should be used with special care. + +CometBFT recommends that an application that detects an invalid vote extension +SHOULD accept it in `ResponseVerifyVoteExtension` and ignore it in its own logic. + +### `FinalizeBlock` + +This method delivers a decided block to the application. The application must +execute the transactions in the block deterministically and update its state +accordingly. Cryptographic commitments to the block and transaction results, +returned via the corresponding parameters in `ResponseFinalizeBlock`, are +included in the header of the next block. CometBFT calls it when a new block +is decided. + +In other words, `FinalizeBlock` encapsulates the current ABCI execution flow of +`BeginBlock`, one or more `DeliverTx`, and `EndBlock` into a single ABCI method. +CometBFT will no longer execute requests for these legacy methods and instead +will just simply call `FinalizeBlock`. + +## Decision + +We will discuss changes to the Cosmos SDK to implement ABCI 2.0 in two distinct +phases, `VoteExtensions` and `FinalizeBlock`. + +### `VoteExtensions` + +Similarly for `PrepareProposal` and `ProcessProposal`, we propose to introduce +two new handlers that an application can implement in order to provide and verify +vote extensions. + +We propose the following new handlers for applications to implement: + +```go +type ExtendVoteHandler func(sdk.Context, abci.RequestExtendVote) abci.ResponseExtendVote +type VerifyVoteExtensionHandler func(sdk.Context, abci.RequestVerifyVoteExtension) abci.ResponseVerifyVoteExtension +``` + +A new execution state, `voteExtensionState`, will be introduced and provided as +the `Context` that is supplied to both handlers. It will contain relevant metadata +such as the block height and block hash. Note, `voteExtensionState` is never +committed and will exist as ephemeral state only in the context of a single block. + +If an application decides to implement `ExtendVoteHandler`, it must return a +non-nil `ResponseExtendVote.VoteExtension`. + +Recall, an implementation of `ExtendVoteHandler` does NOT need to be deterministic, +however, given a set of vote extensions, `VerifyVoteExtensionHandler` must be +deterministic, otherwise the chain may suffer from liveness faults. In addition, +recall CometBFT proceeds in rounds for each height, so if a decision cannot be +made about about a block proposal at a given height, CometBFT will proceed to the +next round and thus will execute `ExtendVote` and `VerifyVoteExtension` again for +the new round for each validator until 2/3 valid pre-commits can be obtained. + +Given the broad scope of potential implementations and use-cases of vote extensions, +and how to verify them, most applications should choose to implement the handlers +through a single handler type, which can have any number of dependencies injected +such as keepers. In addition, this handler type could contain some notion of +volatile vote extension state management which would assist in vote extension +verification. This state management could be ephemeral or could be some form of +on-disk persistence. + +Example: + +```go +// VoteExtensionHandler implements an Oracle vote extension handler. +type VoteExtensionHandler struct { + cdc Codec + mk MyKeeper + state VoteExtState // This could be a map or a DB connection object +} + +// ExtendVoteHandler can do something with h.mk and possibly h.state to create +// a vote extension, such as fetching a series of prices for supported assets. +func (h VoteExtensionHandler) ExtendVoteHandler(ctx sdk.Context, req abci.RequestExtendVote) abci.ResponseExtendVote { + prices := GetPrices(ctx, h.mk.Assets()) + bz, err := EncodePrices(h.cdc, prices) + if err != nil { + panic(fmt.Errorf("failed to encode prices for vote extension: %w", err)) + } + + // store our vote extension at the given height + // + // NOTE: Vote extensions can be overridden since we can timeout in a round. + SetPrices(h.state, req, bz) + + return abci.ResponseExtendVote{VoteExtension: bz} +} + +// VerifyVoteExtensionHandler can do something with h.state and req to verify +// the req.VoteExtension field, such as ensuring the provided oracle prices are +// within some valid range of our prices. +func (h VoteExtensionHandler) VerifyVoteExtensionHandler(ctx sdk.Context, req abci.RequestVerifyVoteExtension) abci.ResponseVerifyVoteExtension { + prices, err := DecodePrices(h.cdc, req.VoteExtension) + if err != nil { + log("failed to decode vote extension", "err", err) + return abci.ResponseVerifyVoteExtension{Status: REJECT} + } + + if err := ValidatePrices(h.state, req, prices); err != nil { + log("failed to validate vote extension", "prices", prices, "err", err) + return abci.ResponseVerifyVoteExtension{Status: REJECT} + } + + // store updated vote extensions at the given height + // + // NOTE: Vote extensions can be overridden since we can timeout in a round. + SetPrices(h.state, req, req.VoteExtension) + + return abci.ResponseVerifyVoteExtension{Status: ACCEPT} +} +``` + +#### Vote Extension Propagation & Verification + +As mentioned previously, vote extensions for height `H` are only made available +to the proposer at height `H+1` during `PrepareProposal`. However, in order to +make vote extensions useful, all validators should have access to the agreed upon +vote extensions at height `H` during `H+1`. + +Since CometBFT includes all the vote extension signatures in `RequestPrepareProposal`, +we propose that the proposing validator manually "inject" the vote extensions +along with their respective signatures via a special transaction, `VoteExtsTx`, +into the block proposal during `PrepareProposal`. The `VoteExtsTx` will be +populated with a single `ExtendedCommitInfo` object which is received directly +from `RequestPrepareProposal`. + +For convention, the `VoteExtsTx` transaction should be the first transaction in +the block proposal, although chains can implement their own preferences. For +safety purposes, we also propose that the proposer itself verify all the vote +extension signatures it receives in `RequestPrepareProposal`. + +A validator, upon a `RequestProcessProposal`, will receive the injected `VoteExtsTx` +which includes the vote extensions along with their signatures. If no such transaction +exists, the validator MUST REJECT the proposal. + +When a validator inspects a `VoteExtsTx`, it will evaluate each `SignedVoteExtension`. +For each signed vote extension, the validator will generate the signed bytes and +verify the signature. At least 2/3 valid signatures, based on voting power, must +be received in order for the block proposal to be valid, otherwise the validator +MUST REJECT the proposal. + +In order to have the ability to validate signatures, `BaseApp` must have access +to the `x/staking` module, since this module stores an index from consensus +address to public key. However, we will avoid a direct dependency on `x/staking` +and instead rely on an interface instead. In addition, the Cosmos SDK will expose +a default signature verification method which applications can use: + +```go +type ValidatorStore interface { + GetValidatorByConsAddr(sdk.Context, cryptotypes.Address) (cryptotypes.PubKey, error) +} + +// ValidateVoteExtensions is a function that an application can execute in +// ProcessProposal to verify vote extension signatures. +func (app *BaseApp) ValidateVoteExtensions(ctx sdk.Context, currentHeight int64, extCommit abci.ExtendedCommitInfo) error { + for _, vote := range extCommit.Votes { + if !vote.SignedLastBlock || len(vote.VoteExtension) == 0 { + continue + } + + valConsAddr := cmtcrypto.Address(vote.Validator.Address) + + validator, err := app.validatorStore.GetValidatorByConsAddr(ctx, valConsAddr) + if err != nil { + return fmt.Errorf("failed to get validator %s for vote extension", valConsAddr) + } + + cmtPubKey, err := validator.CmtConsPublicKey() + if err != nil { + return fmt.Errorf("failed to convert public key: %w", err) + } + + if len(vote.ExtensionSignature) == 0 { + return fmt.Errorf("received a non-empty vote extension with empty signature for validator %s", valConsAddr) + } + + cve := cmtproto.CanonicalVoteExtension{ + Extension: vote.VoteExtension, + Height: currentHeight - 1, // the vote extension was signed in the previous height + Round: int64(extCommit.Round), + ChainId: app.GetChainID(), + } + + extSignBytes, err := cosmosio.MarshalDelimited(&cve) + if err != nil { + return fmt.Errorf("failed to encode CanonicalVoteExtension: %w", err) + } + + if !cmtPubKey.VerifySignature(extSignBytes, vote.ExtensionSignature) { + return errors.New("received vote with invalid signature") + } + + return nil + } +} +``` + +Once at least 2/3 signatures, by voting power, are received and verified, the +validator can use the vote extensions to derive additional data or come to some +decision based on the vote extensions. + +> NOTE: It is very important to state, that neither the vote propagation technique +> nor the vote extension verification mechanism described above is required for +> applications to implement. In other words, a proposer is not required to verify +> and propagate vote extensions along with their signatures nor are proposers +> required to verify those signatures. An application can implement it's own +> PKI mechanism and use that to sign and verify vote extensions. + +#### Vote Extension Persistence + +In certain contexts, it may be useful or necessary for applications to persist +data derived from vote extensions. In order to facilitate this use case, we +propose to allow application developers to manually retrieve the `finalizeState` +context (see [`FinalizeBlock`](#finalizeblock-1) below). Using this context, +state can be directly written to `finalizeState`, which will be used during +`FinalizeBlock` and eventually committed to the application state. Note, since +`ProcessProposal` can timeout and thus require another round of consensus, we +will reset `finalizeState` in the beginning of `ProcessProposal`. + +A `ProcessProposal` handler could look like the following: + +```go +func (h MyHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { + return func(ctx sdk.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal { + for _, txBytes := range req.Txs { + _, err := h.app.ProcessProposalVerifyTx(txBytes) + if err != nil { + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT} + } + } + + fCtx := h.app.GetFinalizeState() + + // Any state changes that occur on the provided fCtx WILL be written to state! + h.myKeeper.SetVoteExtResult(fCtx, ...) + + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT} + } +} +``` + +### `FinalizeBlock` + +The existing ABCI methods `BeginBlock`, `DeliverTx`, and `EndBlock` have existed +since the dawn of ABCI-based applications. Thus, applications, tooling, and developers +have grown used to these methods and their use-cases. Specifically, `BeginBlock` +and `EndBlock` have grown to be pretty integral and powerful within ABCI-based +applications. E.g. an application might want to run distribution and inflation +related operations prior to executing transactions and then have staking related +changes to happen after executing all transactions. + +We propose to keep `BeginBlock` and `EndBlock` within the SDK's core module +interfaces only so application developers can continue to build against existing +execution flows. However, we will remove `BeginBlock`, `DeliverTx` and `EndBlock` +from the SDK's `BaseApp` implementation and thus the ABCI surface area. + +What will then exist is a single `FinalizeBlock` execution flow. Specifically, in +`FinalizeBlock` we will execute the application's `BeginBlock`, followed by +execution of all the transactions, finally followed by execution of the application's +`EndBlock`. + +Note, we will still keep the existing transaction execution mechanics within +`BaseApp`, but all notions of `DeliverTx` will be removed, i.e. `deliverState` +will be replace with `finalizeState`, which will be committed on `Commit`. + +However, there are current parameters and fields that exist in the existing +`BeginBlock` and `EndBlock` ABCI types, such as votes that are used in distribution +and byzantine validators used in evidence handling. These parameters exist in the +`FinalizeBlock` request type, and will need to be passed to the application's +implementations of `BeginBlock` and `EndBlock`. + +This means the Cosmos SDK's core module interfaces will need to be updated to +reflect these parameters. The easiest and most straightforward way to achieve +this is to just pass `RequestFinalizeBlock` to `BeginBlock` and `EndBlock`. +Alternatively, we can create dedicated proxy types in the SDK that reflect these +legacy ABCI types, e.g. `LegacyBeginBlockRequest` and `LegacyEndBlockRequest`. Or, +we can come up with new types and names altogether. + +```go +func (app *BaseApp) FinalizeBlock(req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock { + // merge any state changes from ProcessProposal into the FinalizeBlock state + app.MergeProcessProposalState() + + beginBlockResp := app.beginBlock(ctx, req) + appendBlockEventAttr(beginBlockResp.Events, "begin_block") + + txExecResults := make([]abci.ExecTxResult, 0, len(req.Txs)) + for _, tx := range req.Txs { + result := app.runTx(runTxModeFinalize, tx) + txExecResults = append(txExecResults, result) + } + + endBlockResp := app.endBlock(ctx, req) + appendBlockEventAttr(beginBlockResp.Events, "end_block") + + return abci.ResponseFinalizeBlock{ + TxResults: txExecResults, + Events: joinEvents(beginBlockResp.Events, endBlockResp.Events), + ValidatorUpdates: endBlockResp.ValidatorUpdates, + ConsensusParamUpdates: endBlockResp.ConsensusParamUpdates, + AppHash: nil, + } +} +``` + +#### Events + +Many tools, indexers and ecosystem libraries rely on the existence `BeginBlock` +and `EndBlock` events. Since CometBFT now only exposes `FinalizeBlockEvents`, we +find that it will still be useful for these clients and tools to still query for +and rely on existing events, especially since applications will still define +`BeginBlock` and `EndBlock` implementations. + +In order to facilitate existing event functionality, we propose that all `BeginBlock` +and `EndBlock` events have a dedicated `EventAttribute` with `key=block` and +`value=begin_block|end_block`. The `EventAttribute` will be appended to each event +in both `BeginBlock` and `EndBlock` events`. + + +### Upgrading + +CometBFT defines a consensus parameter, [`VoteExtensionsEnableHeight`](https://github.com/cometbft/cometbft/blob/v0.38.0-alpha.1/spec/abci/abci%2B%2B_app_requirements.md#abciparamsvoteextensionsenableheight), +which specifies the height at which vote extensions are enabled and **required**. +If the value is set to zero, which is the default, then vote extensions are +disabled and an application is not required to implement and use vote extensions. + +However, if the value `H` is positive, at all heights greater than the configured +height `H` vote extensions must be present (even if empty). When the configured +height `H` is reached, `PrepareProposal` will not include vote extensions yet, +but `ExtendVote` and `VerifyVoteExtension` will be called. Then, when reaching +height `H+1`, `PrepareProposal` will include the vote extensions from height `H`. + +It is very important to note, for all heights after H: + +* Vote extensions CANNOT be disabled +* They are mandatory, i.e. all pre-commit messages sent MUST have an extension + attached (even if empty) + +When an application updates to the Cosmos SDK version with CometBFT v0.38 support, +in the upgrade handler it must ensure to set the consensus parameter +`VoteExtensionsEnableHeight` to the correct value. E.g. if an application is set +to perform an upgrade at height `H`, then the value of `VoteExtensionsEnableHeight` +should be set to any value `>=H+1`. This means that at the upgrade height, `H`, +vote extensions will not be enabled yet, but at height `H+1` they will be enabled. + +## Consequences + +### Backwards Compatibility + +ABCI 2.0 is naturally not backwards compatible with prior versions of the Cosmos SDK +and CometBFT. For example, an application that requests `RequestFinalizeBlock` +to the same application that does not speak ABCI 2.0 will naturally fail. + +In addition, `BeginBlock`, `DeliverTx` and `EndBlock` will be removed from the +application ABCI interfaces and along with the inputs and outputs being modified +in the module interfaces. + +### Positive + +* `BeginBlock` and `EndBlock` semantics remain, so burden on application developers + should be limited. +* Less communication overhead as multiple ABCI requests are condensed into a single + request. +* Sets the groundwork for optimistic execution. +* Vote extensions allow for an entirely new set of application primitives to be + developed, such as in-process price oracles and encrypted mempools. + +### Negative + +* Some existing Cosmos SDK core APIs may need to be modified and thus broken. +* Signature verification in `ProcessProposal` of 100+ vote extension signatures + will add significant performance overhead to `ProcessProposal`. Granted, the + signature verification process can happen concurrently using an error group + with `GOMAXPROCS` goroutines. + +### Neutral + +* Having to manually "inject" vote extensions into the block proposal during + `PrepareProposal` is an awkward approach and takes up block space unnecessarily. +* The requirement of `ResetProcessProposalState` can create a footgun for + application developers if they're not careful, but this is necessary in order + for applications to be able to commit state from vote extension computation. + +## Further Discussions + +Future discussions include design and implementation of ABCI 3.0, which is a +continuation of ABCI++ and the general discussion of optimistic execution. + +## References + +* [ADR 060: ABCI 1.0 (Phase I)](adr-060-abci-1.0.md) diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-065-store-v2.md b/versioned_docs/version-0.47/integrate/architecture/adr-065-store-v2.md new file mode 100644 index 000000000..67c1830fd --- /dev/null +++ b/versioned_docs/version-0.47/integrate/architecture/adr-065-store-v2.md @@ -0,0 +1,290 @@ +# ADR-065: Store V2 + +## Changelog + +* Feb 14, 2023: Initial Draft (@alexanderbez) + +## Status + +DRAFT + +## Abstract + +The storage and state primitives that Cosmos SDK based applications have used have +by and large not changed since the launch of the inaugural Cosmos Hub. The demands +and needs of Cosmos SDK based applications, from both developer and client UX +perspectives, have evolved and outgrown the ecosystem since these primitives +were first introduced. + +Over time as these applications have gained significant adoption, many critical +shortcomings and flaws have been exposed in the state and storage primitives of +the Cosmos SDK. + +In order to keep up with the evolving demands and needs of both clients and developers, +a major overhaul to these primitives are necessary. + +## Context + +The Cosmos SDK provides application developers with various storage primitives +for dealing with application state. Specifically, each module contains its own +merkle commitment data structure -- an IAVL tree. In this data structure, a module +can store and retrieve key-value pairs along with Merkle commitments, i.e. proofs, +to those key-value pairs indicating that they do or do not exist in the global +application state. This data structure is the base layer `KVStore`. + +In addition, the SDK provides abstractions on top of this Merkle data structure. +Namely, a root multi-store (RMS) is a collection of each module's `KVStore`. +Through the RMS, the application can serve queries and provide proofs to clients +in addition to provide a module access to its own unique `KVStore` though the use +of `StoreKey`, which is an OCAP primitive. + +There are further layers of abstraction that sit between the RMS and the underlying +IAVL `KVStore`. A `GasKVStore` is responsible for tracking gas IO consumption for +state machine reads and writes. A `CacheKVStore` is responsible for providing a +way to cache reads and buffer writes to make state transitions atomic, e.g. +transaction execution or governance proposal execution. + +There are a few critical drawbacks to these layers of abstraction and the overall +design of storage in the Cosmos SDK: + +* Since each module has its own IAVL `KVStore`, commitments are not [atomic](https://github.com/cosmos/cosmos-sdk/issues/14625) + * Note, we can still allow modules to have their own IAVL `KVStore`, but the + IAVL library will need to support the ability to pass a DB instance as an + argument to various IAVL APIs. +* Since IAVL is responsible for both state storage and commitment, running an + archive node becomes increasingly expensive as disk space grows exponentially. +* As the size of a network increases, various performance bottlenecks start to + emerge in many areas such as query performance, network upgrades, state + migrations, and general application performance. +* Developer UX is poor as it does not allow application developers to experiment + with different types of approaches to storage and commitments, along with the + complications of many layers of abstractions referenced above. + +See the [Storage Discussion](https://github.com/cosmos/cosmos-sdk/discussions/13545) for more information. + +## Alternatives + +There was a previous attempt to refactor the storage layer described in [ADR-040](adr-040-storage-and-smt-state-commitments.md). +However, this approach mainly stems on the short comings of IAVL and various performance +issues around it. While there was a (partial) implementation of [ADR-040](adr-040-storage-and-smt-state-commitments.md), +it was never adopted for a variety of reasons, such as the reliance on using an +SMT, which was more in a research phase, and some design choices that couldn't +be fully agreed upon, such as the snap-shotting mechanism that would result in +massive state bloat. + +## Decision + +We propose to build upon some of the great ideas introduced in [ADR-040](adr-040-storage-and-smt-state-commitments.md), +while being a bit more flexible with the underlying implementations and overall +less intrusive. Specifically, we propose to: + +* Separate the concerns of state commitment (**SC**), needed for consensus, and + state storage (**SS**), needed for state machine and clients. +* Reduce layers of abstractions necessary between the RMS and underlying stores. +* Provide atomic module store commitments by providing a batch database object + to core IAVL APIs. +* Reduce complexities in the `CacheKVStore` implementation while also improving + performance[3]. + +Furthermore, we will keep the IAVL is the backing [commitment](https://cryptography.fandom.com/wiki/Commitment_scheme) +store for the time being. While we might not fully settle on the use of IAVL in +the long term, we do not have strong empirical evidence to suggest a better +alternative. Given that the SDK provides interfaces for stores, it should be sufficient +to change the backing commitment store in the future should evidence arise to +warrant a better alternative. However there is promising work being done to IAVL +that should result in significant performance improvement [1,2]. + +### Separating SS and SC + +By separating SS and SC, it will allow for us to optimize against primary use cases +and access patterns to state. Specifically, The SS layer will be responsible for +direct access to data in the form of (key, value) pairs, whereas the SC layer (IAVL) +will be responsible for committing to data and providing Merkle proofs. + +Note, the underlying physical storage database will be the same between both the +SS and SC layers. So to avoid collisions between (key, value) pairs, both layers +will be namespaced. + +#### State Commitment (SC) + +Given that the existing solution today acts as both SS and SC, we can simply +repurpose it to act solely as the SC layer without any significant changes to +access patterns or behavior. In other words, the entire collection of existing +IAVL-backed module `KVStore`s will act as the SC layer. + +However, in order for the SC layer to remain lightweight and not duplicate a +majority of the data held in the SS layer, we encourage node operators to keep +tight pruning strategies. + +#### State Storage (SS) + +In the RMS, we will expose a *single* `KVStore` backed by the same physical +database that backs the SC layer. This `KVStore` will be explicitly namespaced +to avoid collisions and will act as the primary storage for (key, value) pairs. + +While we most likely will continue the use of `cosmos-db`, or some local interface, +to allow for flexibility and iteration over preferred physical storage backends +as research and benchmarking continues. However, we propose to hardcode the use +of RocksDB as the primary physical storage backend. + +Since the SS layer will be implemented as a `KVStore`, it will support the +following functionality: + +* Range queries +* CRUD operations +* Historical queries and versioning +* Pruning + +The RMS will keep track of all buffered writes using a dedicated and internal +`MemoryListener` for each `StoreKey`. For each block height, upon `Commit`, the +SS layer will write all buffered (key, value) pairs under a [RocksDB user-defined timestamp](https://github.com/facebook/rocksdb/wiki/User-defined-Timestamp-%28Experimental%29) column +family using the block height as the timestamp, which is an unsigned integer. +This will allow a client to fetch (key, value) pairs at historical and current +heights along with making iteration and range queries relatively performant as +the timestamp is the key suffix. + +Note, we choose not to use a more general approach of allowing any embedded key/value +database, such as LevelDB or PebbleDB, using height key-prefixed keys to +effectively version state because most of these databases use variable length +keys which would effectively make actions likes iteration and range queries less +performant. + +Since operators might want pruning strategies to differ in SS compared to SC, +e.g. having a very tight pruning strategy in SC while having a looser pruning +strategy for SS, we propose to introduce an additional pruning configuration, +with parameters that are identical to what exists in the SDK today, and allow +operators to control the pruning strategy of the SS layer independently of the +SC layer. + +Note, the SC pruning strategy must be congruent with the operator's state sync +configuration. This is so as to allow state sync snapshots to execute successfully, +otherwise, a snapshot could be triggered on a height that is not available in SC. + +#### State Sync + +The state sync process should be largely unaffected by the separation of the SC +and SS layers. However, if a node syncs via state sync, the SS layer of the node +will not have the state synced height available, since the IAVL import process is +not setup in way to easily allow direct key/value insertion. A modification of +the IAVL import process would be necessary to facilitate having the state sync +height available. + +Note, this is not problematic for the state machine itself because when a query +is made, the RMS will automatically direct the query correctly (see [Queries](#queries)). + +#### Queries + +To consolidate the query routing between both the SC and SS layers, we propose to +have a notion of a "query router" that is constructed in the RMS. This query router +will be supplied to each `KVStore` implementation. The query router will route +queries to either the SC layer or the SS layer based on a few parameters. If +`prove: true`, then the query must be routed to the SC layer. Otherwise, if the +query height is available in the SS layer, the query will be served from the SS +layer. Otherwise, we fall back on the SC layer. + +If no height is provided, the SS layer will assume the latest height. The SS +layer will store a reverse index to lookup `LatestVersion -> timestamp(version)` +which is set on `Commit`. + +#### Proofs + +Since the SS layer is naturally a storage layer only, without any commitments +to (key, value) pairs, it cannot provide Merkle proofs to clients during queries. + +Since the pruning strategy against the SC layer is configured by the operator, +we can therefore have the RMS route the query SC layer if the version exists and +`prove: true`. Otherwise, the query will fall back to the SS layer without a proof. + +We could explore the idea of using state snapshots to rebuild an in-memory IAVL +tree in real time against a version closest to the one provided in the query. +However, it is not clear what the performance implications will be of this approach. + +### Atomic Commitment + +We propose to modify the existing IAVL APIs to accept a batch DB object instead +of relying on an internal batch object in `nodeDB`. Since each underlying IAVL +`KVStore` shares the same DB in the SC layer, this will allow commits to be +atomic. + +Specifically, we propose to: + +* Remove the `dbm.Batch` field from `nodeDB` +* Update the `SaveVersion` method of the `MutableTree` IAVL type to accept a batch object +* Update the `Commit` method of the `CommitKVStore` interface to accept a batch object +* Create a batch object in the RMS during `Commit` and pass this object to each + `KVStore` +* Write the database batch after all stores have committed successfully + +Note, this will require IAVL to be updated to not rely or assume on any batch +being present during `SaveVersion`. + +## Consequences + +As a result of a new store V2 package, we should expect to see improved performance +for queries and transactions due to the separation of concerns. We should also +expect to see improved developer UX around experimentation of commitment schemes +and storage backends for further performance, in addition to a reduced amount of +abstraction around KVStores making operations such as caching and state branching +more intuitive. + +However, due to the proposed design, there are drawbacks around providing state +proofs for historical queries. + +### Backwards Compatibility + +This ADR proposes changes to the storage implementation in the Cosmos SDK through +an entirely new package. Interfaces may be borrowed and extended from existing +types that exist in `store`, but no existing implementations or interfaces will +be broken or modified. + +### Positive + +* Improved performance of independent SS and SC layers +* Reduced layers of abstraction making storage primitives easier to understand +* Atomic commitments for SC +* Redesign of storage types and interfaces will allow for greater experimentation + such as different physical storage backends and different commitment schemes + for different application modules + +### Negative + +* Providing proofs for historical state is challenging + +### Neutral + +* Keeping IAVL as the primary commitment data structure, although drastic + performance improvements are being made + +## Further Discussions + +### Module Storage Control + +Many modules store secondary indexes that are typically solely used to support +client queries, but are actually not needed for the state machine's state +transitions. What this means is that these indexes technically have no reason to +exist in the SC layer at all, as they take up unnecessary space. It is worth +exploring what an API would look like to allow modules to indicate what (key, value) +pairs they want to be persisted in the SC layer, implicitly indicating the SS +layer as well, as opposed to just persisting the (key, value) pair only in the +SS layer. + +### Historical State Proofs + +It is not clear what the importance or demand is within the community of providing +commitment proofs for historical state. While solutions can be devised such as +rebuilding trees on the fly based on state snapshots, it is not clear what the +performance implications are for such solutions. + +### Physical DB Backends + +This ADR proposes usage of RocksDB to utilize user-defined timestamps as a +versioning mechanism. However, other physical DB backends are available that may +offer alternative ways to implement versioning while also providing performance +improvements over RocksDB. E.g. PebbleDB supports MVCC timestamps as well, but +we'll need to explore how PebbleDB handles compaction and state growth over time. + +## References + +* [1] https://github.com/cosmos/iavl/pull/676 +* [2] https://github.com/cosmos/iavl/pull/664 +* [3] https://github.com/cosmos/cosmos-sdk/issues/14990 diff --git a/versioned_docs/version-0.47/integrate/architecture/adr-template.md b/versioned_docs/version-0.47/integrate/architecture/adr-template.md index dae4dfd44..dcf07343c 100644 --- a/versioned_docs/version-0.47/integrate/architecture/adr-template.md +++ b/versioned_docs/version-0.47/integrate/architecture/adr-template.md @@ -8,52 +8,75 @@ {DRAFT | PROPOSED} Not Implemented -> Please have a look at the [PROCESS](./PROCESS.md#adr-status) page. +> Please have a look at the [PROCESS](PROCESS.md#adr-status) page. > Use DRAFT if the ADR is in a draft stage (draft PR) or PROPOSED if it's in review. ## Abstract -> "If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the ADR. +> "If you can't explain it simply, you don't understand it well enough." Provide +> a simplified and layman-accessible explanation of the ADR. > A short (~200 word) description of the issue being addressed. ## Context -> This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. It should clearly explain the problem and motivation that the proposal aims to resolve. +> This section describes the forces at play, including technological, political, +> social, and project local. These forces are probably in tension, and should be +> called out as such. The language in this section is value-neutral. It is simply +> describing facts. It should clearly explain the problem and motivation that the +> proposal aims to resolve. > {context body} +## Alternatives + +> This section describes alternative designs to the chosen design. This section +> is important and if an adr does not have any alternatives then it should be +> considered that the ADR was not thought through. + ## Decision -> This section describes our response to these forces. It is stated in full sentences, with active voice. "We will ..." +> This section describes our response to these forces. It is stated in full +> sentences, with active voice. "We will ..." > {decision body} ## Consequences -> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. +> This section describes the resulting context, after applying the decision. All +> consequences should be listed here, not just the "positive" ones. A particular +> decision may have positive, negative, and neutral consequences, but all of them +> affect the team and project in the future. ### Backwards Compatibility -> All ADRs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The ADR must explain how the author proposes to deal with these incompatibilities. ADR submissions without a sufficient backwards compatibility treatise may be rejected outright. +> All ADRs that introduce backwards incompatibilities must include a section +> describing these incompatibilities and their severity. The ADR must explain +> how the author proposes to deal with these incompatibilities. ADR submissions +> without a sufficient backwards compatibility treatise may be rejected outright. ### Positive -{positive consequences} +> {positive consequences} ### Negative -{negative consequences} +> {negative consequences} ### Neutral -{neutral consequences} +> {neutral consequences} ## Further Discussions -While an ADR is in the DRAFT or PROPOSED stage, this section should contain a summary of issues to be solved in future iterations (usually referencing comments from a pull-request discussion). -Later, this section can optionally list ideas or improvements the author or reviewers found during the analysis of this ADR. +> While an ADR is in the DRAFT or PROPOSED stage, this section should contain a +> summary of issues to be solved in future iterations (usually referencing comments +> from a pull-request discussion). +> +> Later, this section can optionally list ideas or improvements the author or +> reviewers found during the analysis of this ADR. ## Test Cases [optional] -Test cases for an implementation are mandatory for ADRs that are affecting consensus changes. Other ADRs can choose to include links to test cases if applicable. +Test cases for an implementation are mandatory for ADRs that are affecting consensus +changes. Other ADRs can choose to include links to test cases if applicable. ## References diff --git a/versioned_docs/version-0.47/integrate/building-apps/00-app-go.md b/versioned_docs/version-0.47/integrate/building-apps/00-app-go.md index f4af6dcfc..054f06b9b 100644 --- a/versioned_docs/version-0.47/integrate/building-apps/00-app-go.md +++ b/versioned_docs/version-0.47/integrate/building-apps/00-app-go.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: integrateSidebar --- # Overview of `app.go` diff --git a/versioned_docs/version-0.47/integrate/building-apps/01-app-go-v2.md b/versioned_docs/version-0.47/integrate/building-apps/01-app-go-v2.md index 926d86dbb..6d8dc6faf 100644 --- a/versioned_docs/version-0.47/integrate/building-apps/01-app-go-v2.md +++ b/versioned_docs/version-0.47/integrate/building-apps/01-app-go-v2.md @@ -1,12 +1,13 @@ --- sidebar_position: 1 +dislayed_sidebar: integrateSidebar --- # Overview of `app_v2.go` :::note Synopsis -The Cosmos SDK allows much easier wiring of an `app.go` thanks to App Wiring and [`depinject`](../tooling/02-depinject.md). +The Cosmos SDK allows much easier wiring of an `app.go` thanks to App Wiring and [`depinject`](../libraries/01-depinject.md). Learn more about the rationale of App Wiring in [ADR-057](../architecture/adr-057-app-wiring.md). ::: @@ -16,7 +17,8 @@ Learn more about the rationale of App Wiring in [ADR-057](../architecture/adr-05 ### Pre-requisite Readings * [ADR 057: App Wiring](../architecture/adr-057-app-wiring.md) -* [Depinject Documentation](../tooling/02-depinject.md) +* [Depinject Documentation](../libraries/01-depinject.md) +* [Modules depinject-ready](../building-modules/15-depinject.md) ::: diff --git a/versioned_docs/version-0.47/integrate/building-apps/02-app-mempool.md b/versioned_docs/version-0.47/integrate/building-apps/02-app-mempool.md index b32b96547..4919207c8 100644 --- a/versioned_docs/version-0.47/integrate/building-apps/02-app-mempool.md +++ b/versioned_docs/version-0.47/integrate/building-apps/02-app-mempool.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: integrateSidebar --- # Application mempool @@ -17,7 +18,7 @@ Notably it introduces the `PrepareProposal` and `ProcessProposal` steps of ABCI+ ### Pre-requisite Readings -* [BaseApp](../core/00-baseapp.md) +* [BaseApp](../../develop/advanced-concepts/00-baseapp.md) ::: @@ -43,15 +44,14 @@ all transactions, it can provide greater control over transaction ordering. Allowing the application to handle ordering enables the application to define how it would like the block constructed. -The Cosmos SDK defines the `DefaultProposalHandler` type, which provides applications with -`PrepareProposal` and `ProcessProposal` handlers. +Currently, there is a default `PrepareProposal` implementation provided by the application. ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/baseapp.go#L868-L916 ``` This default implementation can be overridden by the application developer in -favor of a custom implementation in [`app.go`](./01-app-go-v2.md): +favor of a custom implementation in [`app.go`](01-app-go-v2.md): ```go prepareOpt := func(app *baseapp.BaseApp) { @@ -81,7 +81,7 @@ Here is the implementation of the default implementation: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/baseapp/baseapp.go#L927-L942 ``` -Like `PrepareProposal` this implementation is the default and can be modified by the application developer in [`app.go`](./01-app-go-v2.md): +Like `PrepareProposal` this implementation is the default and can be modified by the application developer in [`app.go`](01-app-go-v2.md): ```go processOpt := func(app *baseapp.BaseApp) { @@ -103,7 +103,7 @@ Namely, the SDK provides the following mempools: * [Sender Nonce Mempool](#sender-nonce-mempool) * [Priority Nonce Mempool](#priority-nonce-mempool) -The default SDK is a [No-op Mempool](#no-op-mempool), but it can be replaced by the application developer in [`app.go`](./01-app-go-v2.md): +The default SDK is a [No-op Mempool](#no-op-mempool), but it can be replaced by the application developer in [`app.go`](01-app-go-v2.md): ```go nonceMempool := mempool.NewSenderNonceMempool() @@ -117,9 +117,6 @@ A no-op mempool is a mempool where transactions are completely discarded and ign When this mempool is used, it assumed that an application will rely on CometBFT's transaction ordering defined in `RequestPrepareProposal`, which is FIFO-ordered by default. -> Note: If a NoOp mempool is used, PrepareProposal and ProcessProposal both should be aware of this as -> PrepareProposal could include transactions that could fail verification in ProcessProposal. - ### Sender Nonce Mempool The nonce mempool is a mempool that keeps transactions from an sorted by nonce in order to avoid the issues with nonces. diff --git a/versioned_docs/version-0.47/integrate/building-apps/03-app-upgrade.md b/versioned_docs/version-0.47/integrate/building-apps/03-app-upgrade.md index d60e78117..804f98515 100644 --- a/versioned_docs/version-0.47/integrate/building-apps/03-app-upgrade.md +++ b/versioned_docs/version-0.47/integrate/building-apps/03-app-upgrade.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +dislayed_sidebar: integrateSidebar --- # Application upgrade diff --git a/versioned_docs/version-0.47/integrate/building-apps/_category_.json b/versioned_docs/version-0.47/integrate/building-apps/_category_.json index de6617ddc..342732cce 100644 --- a/versioned_docs/version-0.47/integrate/building-apps/_category_.json +++ b/versioned_docs/version-0.47/integrate/building-apps/_category_.json @@ -1,5 +1,5 @@ { "label": "Building Apps", - "position": 4, + "position": 0, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/building-modules/intro.md b/versioned_docs/version-0.47/integrate/building-modules/00-intro.md similarity index 73% rename from versioned_docs/version-0.46/integrate/building-modules/intro.md rename to versioned_docs/version-0.47/integrate/building-modules/00-intro.md index a6b088549..226c2caf6 100644 --- a/versioned_docs/version-0.46/integrate/building-modules/intro.md +++ b/versioned_docs/version-0.47/integrate/building-modules/00-intro.md @@ -1,23 +1,29 @@ - +--- +sidebar_position: 1 +--- # Introduction to Cosmos SDK Modules -Modules define most of the logic of Cosmos SDK applications. Developers compose modules together using the Cosmos SDK to build their custom application-specific blockchains. This document outlines the basic concepts behind SDK modules and how to approach module management. {synopsis} +:::note Synopsis +Modules define most of the logic of Cosmos SDK applications. Developers compose modules together using the Cosmos SDK to build their custom application-specific blockchains. This document outlines the basic concepts behind SDK modules and how to approach module management. +::: -## Pre-requisite Readings +:::note -* [Anatomy of a Cosmos SDK application](../basics/app-anatomy.md) {prereq} -* [Lifecycle of a Cosmos SDK transaction](../basics/tx-lifecycle.md) {prereq} +### Pre-requisite Readings + +* [Anatomy of a Cosmos SDK application](../../develop/high-level-concepts/00-overview-app.md) +* [Lifecycle of a Cosmos SDK transaction](../../develop/high-level-concepts/01-tx-lifecycle.md) + +::: ## Role of Modules in a Cosmos SDK Application -The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../core/baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../core/store.md#multistore) to persist state, a [server](../core/node.md) to form a full-node and [interfaces](./module-interfaces.md) to handle queries. +The Cosmos SDK can be thought of as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../../develop/advanced-concepts/00-baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../../develop/advanced-concepts/04-store.md#multistore) to persist state, a [server](../../develop/advanced-concepts/03-node.md) to form a full-node and [interfaces](09-module-interfaces.md) to handle queries. On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source Cosmos SDK modules, making it increasingly easier to build complex blockchain applications. -Cosmos SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../core/store.md), as well as a subset of [message types](./messages-and-queries.md#messages). These messages are routed by one of the main components of Cosmos SDK core, [`BaseApp`](../core/baseapp.md), to a module Protobuf [`Msg` service](./msg-services.md) that defines them. +Cosmos SDK modules can be seen as little state-machines within the state-machine. They generally define a subset of the state using one or more `KVStore`s in the [main multistore](../../develop/advanced-concepts/04-store.md), as well as a subset of [message types](02-messages-and-queries.md#messages). These messages are routed by one of the main components of Cosmos SDK core, [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md), to a module Protobuf [`Msg` service](03-msg-services.md) that defines them. ```text + @@ -59,7 +65,7 @@ Cosmos SDK modules can be seen as little state-machines within the state-machine | +--------------------------+ | - | Return result to the underlying consensus engine (e.g. Tendermint) + | Return result to the underlying consensus engine (e.g. CometBFT) | (0=Ok, 1=Err) v ``` @@ -70,23 +76,19 @@ As a result of this architecture, building a Cosmos SDK application usually revo While there are no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them: -* **Composability**: Cosmos SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./keeper.md). -* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. -* **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. +* **Composability**: Cosmos SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-cosmos-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](06-keeper.md). +* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../../develop/advanced-concepts/10-ocap.md) of the Cosmos SDK. +* **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](06-keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. ## Main Components of Cosmos SDK Modules Modules are by convention defined in the `./x/` subfolder (e.g. the `bank` module will be defined in the `./x/bank` folder). They generally share the same core components: -* A [`keeper`](./keeper.md), used to access the module's store(s) and update the state. -* A [`Msg` service](./messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../core/baseapp.md#message-routing) and trigger state-transitions. -* A [query service](./query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../core/baseapp.md#query-routing). +* A [`keeper`](06-keeper.md), used to access the module's store(s) and update the state. +* A [`Msg` service](02-messages-and-queries.md#messages), used to process messages when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#message-routing) and trigger state-transitions. +* A [query service](04-query-services.md), used to process user queries when they are routed to the module by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#query-routing). * Interfaces, for end users to query the subset of the state defined by the module and create `message`s of the custom types defined in the module. -In addition to these components, modules implement the `AppModule` interface in order to be managed by the [`module manager`](./module-manager.md). - -Please refer to the [structure document](./structure.md) to learn about the recommended structure of a module's directory. - -## Next {hide} +In addition to these components, modules implement the `AppModule` interface in order to be managed by the [`module manager`](01-module-manager.md). -Read more on the [`AppModule` interface and the `module manager`](./module-manager.md) {hide} +Please refer to the [structure document](11-structure.md) to learn about the recommended structure of a module's directory. diff --git a/versioned_docs/version-0.47/integrate/building-modules/01-module-manager.md b/versioned_docs/version-0.47/integrate/building-modules/01-module-manager.md index 8003e37dd..0993a5999 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/01-module-manager.md +++ b/versioned_docs/version-0.47/integrate/building-modules/01-module-manager.md @@ -5,14 +5,14 @@ sidebar_position: 1 # Module Manager :::note Synopsis -Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../core/00-baseapp.md#routing), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../basics/00-app-anatomy.md#begingblocker-and-endblocker). +Cosmos SDK modules need to implement the [`AppModule` interfaces](#application-module-interfaces), in order to be managed by the application's [module manager](#module-manager). The module manager plays an important role in [`message` and `query` routing](../../develop/advanced-concepts/00-baseapp.md#msg-service-router), and allows application developers to set the order of execution of a variety of functions like [`BeginBlocker` and `EndBlocker`](../../develop/high-level-concepts/00-overview-app#beginblocker-and-endblocker). ::: :::note ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](./01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: @@ -36,10 +36,12 @@ The above interfaces are mostly embedding smaller interfaces (extension interfac * [`HasConsensusVersion`](#hasconsensusversion): The extension interface for declaring a module consensus version. * [`BeginBlockAppModule`](#beginblockappmodule): The extension interface that contains information about the `AppModule` and `BeginBlock`. * [`EndBlockAppModule`](#endblockappmodule): The extension interface that contains information about the `AppModule` and `EndBlock`. +* [`HasPrecommit`](#hasprecommit): The extension interface that contains information about the `AppModule` and `Precommit`. +* [`HasPrepareCheckState`](#haspreparecheckstate): The extension interface that contains information about the `AppModule` and `PrepareCheckState`. -The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../basics/00-app-anatomy.md#core-application-file). +The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](../../develop/high-level-concepts/00-overview-app.md#core-application-file). -The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](./06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface extension, such as `BeginBlockAppModule` and `EndBlockAppModule`, also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. +The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface extension, such as `BeginBlockAppModule` and `EndBlockAppModule`, also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application. The usage of extension interfaces allows modules to define only the functionalities they need. For example, a module that does not need an `EndBlock` does not need to define the `EndBlockAppModule` interface and thus the `EndBlock` method. `AppModule` and `AppModuleGenesis` are voluntarily small interfaces, that can take advantage of the `Module` patterns without having to define many placeholder functions. @@ -56,8 +58,8 @@ Let us go through the methods: * `RegisterLegacyAminoCodec(*codec.LegacyAmino)`: Registers the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`. * `RegisterInterfaces(codectypes.InterfaceRegistry)`: Registers a module's interface types and their concrete implementations as `proto.Message`. * `RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)`: Registers gRPC routes for the module. -* `GetTxCmd()`: Returns the root [`Tx` command](./09-module-interfaces.md#tx) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](./02-messages-and-queries.md#queries) defined in the module. -* `GetQueryCmd()`: Return the root [`query` command](./09-module-interfaces.md#query) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. +* `GetTxCmd()`: Returns the root [`Tx` command](09-module-interfaces.md#transaction-commands) for the module. The subcommands of this root command are used by end-users to generate new transactions containing [`message`s](02-messages-and-queries.md#queries) defined in the module. +* `GetQueryCmd()`: Return the root [`query` command](09-module-interfaces.md#query-commands) for the module. The subcommands of this root command are used by end-users to generate new queries to the subset of the state defined by the module. All the `AppModuleBasic` of an application are managed by the [`BasicManager`](#basicmanager). @@ -77,8 +79,8 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/module/module.go#L68 Let us go through the methods: -* `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](./08-genesis.md#genesisstate) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. -* `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](./08-genesis.md#validategenesis) function defined by the module developer. +* `DefaultGenesis(codec.JSONCodec)`: Returns a default [`GenesisState`](08-genesis.md) for the module, marshalled to `json.RawMessage`. The default `GenesisState` need to be defined by the module developer and is primarily used for testing. +* `ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`: Used to validate the `GenesisState` defined by a module, given in its `json.RawMessage` form. It will usually unmarshall the `json` before running a custom [`ValidateGenesis`](08-genesis.md#validategenesis) function defined by the module developer. ### `AppModuleGenesis` @@ -125,7 +127,7 @@ This interface defines one method. It allows to checks if a module can register https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/module/module.go#L175-L179 ``` -* `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](./07-invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](./07-invariants.md#registry) triggers appropriate logic (most often the chain will be halted). +* `RegisterInvariants(sdk.InvariantRegistry)`: Registers the [`invariants`](07-invariants.md) of the module. If an invariant deviates from its predicted value, the [`InvariantRegistry`](07-invariants.md#invariant-registry) triggers appropriate logic (most often the chain will be halted). ### `HasServices` @@ -167,11 +169,23 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/module/module.go#L20 * `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the end of each block for this module. +### `HasPrecommit` + +`HasPrecommit` is an extension interface from `AppModule`. All modules that have a `Precommit` method implement this interface. + +* `Precommit(sdk.Context)`: This method gives module developers the option to implement logic that is automatically triggered during [`Commit'](../../develop/advanced-concepts/00-baseapp.md#commit) of each block using the [`deliverState`](../../develop/advanced-concepts/00-baseapp.md#state-updates) of the block to be committed. Implement empty if no logic needs to be triggered during `Commit` of each block for this module. + +### `HasPrepareCheckState` + +`HasPrepareCheckState` is an extension interface from `AppModule`. All modules that have a `PrepareCheckState` method implement this interface. + +* `PrepareCheckState(sdk.Context)`: This method gives module developers the option to implement logic that is automatically triggered during [`Commit'](../../develop/advanced-concepts/00-baseapp.md) of each block using the [`checkState`](../../develop/advanced-concepts/00-baseapp.md#state-updates) of the next block. Implement empty if no logic needs to be triggered during `Commit` of each block for this module. + ### Implementing the Application Module Interfaces Typically, the various application module interfaces are implemented in a file called `module.go`, located in the module's folder (e.g. `./x/module/module.go`). -Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./06-keeper.md) as a parameter. +Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](06-keeper.md) as a parameter. ```go // example @@ -203,14 +217,14 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/module/module.go#L74 It implements the following methods: -* `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../basics/00-app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/main/app/app.go#L59-L74) to see an example). -* `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../core/05-encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../basics/00-app-anatomy.md#constructor). +* `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../../develop/high-level-concepts/00-overview-app.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/main/app/app.go#L59-L74) to see an example). +* `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../../develop/advanced-concepts/06-encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../../develop/high-level-concepts/00-overview-app.md#constructor). * `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModuleBasic`. -* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It only calls the modules that implements the `HasGenesisBasics` interfaces. -* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of modules implementing the `HasGenesisBasics` interface. +* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](08-genesis.md#defaultgenesis) function of each module. It only calls the modules that implements the `HasGenesisBasics` interfaces. +* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](08-genesis.md#validategenesis) function of modules implementing the `HasGenesisBasics` interface. * `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules. -* `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../core/07-cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/07-cli.md). -* `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../core/07-cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../core/07-cli.md). +* `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands to the application's [`rootTxCommand`](../../develop/advanced-concepts/07-cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../../develop/advanced-concepts/07-cli.md). +* `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands to the application's [`rootQueryCommand`](../../develop/advanced-concepts/07-cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../../develop/advanced-concepts/07-cli.md). ### `Manager` @@ -222,21 +236,25 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/module/module.go#L24 The module manager is used throughout the application whenever an action on a collection of modules is required. It implements the following methods: -* `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../basics/00-app-anatomy.md#constructor-function). -* `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../basics/00-app-anatomy.md#constructor-function). - To initialize modules successfully, module dependencies should be considered. For example, the `genutil` module must occur after `staking` module so that the pools are properly initialized with tokens from genesis accounts, the `genutils` module must also occur after `auth` so that it can access the params from auth, `capability` module should be initialized before all other modules so that it can initialize any capabilities. -* `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../basics/00-app-anatomy.md#constructor-function). -* `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/00-app-anatomy.md#constructor-function). -* `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../basics/00-app-anatomy.md#constructor-function). +* `NewManager(modules ...AppModule)`: Constructor function. It takes a list of the application's `AppModule`s and builds a new `Manager`. It is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). +* `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](08-genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). + To initialize modules successfully, module dependencies should be considered. For example, the `genutil` module must occur after `staking` module so that the pools are properly initialized with tokens from genesis accounts, the `genutils` module must also occur after `auth` so that it can access the params from auth, IBC's `capability` module should be initialized before all other modules so that it can initialize any capabilities. +* `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](08-genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). +* `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). +* `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). +* `SetOrderPrecommiters(moduleNames ...string)`: Sets the order in which the `Precommit()` function of each module will be called during commit of each block. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). +* `SetOrderPrepareCheckStaters(moduleNames ...string)`: Sets the order in which the `PrepareCheckState()` function of each module will be called during commit of each block. This function is generally called from the application's main [constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). * `SetOrderMigrations(moduleNames ...string)`: Sets the order of migrations to be run. If not set then migrations will be run with an order defined in `DefaultMigrationsOrder`. -* `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./07-invariants.md) of module implementing the `HasInvariants` interface. -* `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./02-messages-and-queries.md#messages) and [`querier`](./04-query-services.md#legacy-queriers) routes. +* `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](07-invariants.md) of module implementing the `HasInvariants` interface. +* `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](02-messages-and-queries.md#messages) and [`querier`](04-query-services.md) routes. * `RegisterServices(cfg Configurator)`: Registers the services of modules implementing the `HasServices` interface. -* `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](./08-genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. -* `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](./08-genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. +* `InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage)`: Calls the [`InitGenesis`](08-genesis.md#initgenesis) function of each module when the application is first started, in the order defined in `OrderInitGenesis`. Returns an `abci.ResponseInitChain` to the underlying consensus engine, which can contain validator updates. +* `ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)`: Calls the [`ExportGenesis`](08-genesis.md#exportgenesis) function of each module, in the order defined in `OrderExportGenesis`. The export constructs a genesis file from a previously existing state, and is mainly used when a hard-fork upgrade of the chain is required. * `ExportGenesisForModules(ctx sdk.Context, cdc codec.JSONCodec, modulesToExport []string)`: Behaves the same as `ExportGenesis`, except takes a list of modules to export. -* `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../core/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](./05-beginblock-endblock.md) function of each modules implementing the `BeginBlockAppModule` interface, in the order defined in `OrderBeginBlockers`. It creates a child [context](../core/02-context.md) with an event manager to aggregate [events](../core/08-events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. -* `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../core/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./05-beginblock-endblock.md) function of each modules implementing the `EndBlockAppModule` interface, in the order defined in `OrderEndBlockers`. It creates a child [context](../core/02-context.md) with an event manager to aggregate [events](../core/08-events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). +* `BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)`: At the beginning of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and, in turn, calls the [`BeginBlock`](05-beginblock-endblock.md) function of each modules implementing the `BeginBlockAppModule` interface, in the order defined in `OrderBeginBlockers`. It creates a child [context](../../develop/advanced-concepts/02-context.md) with an event manager to aggregate [events](../../develop/advanced-concepts/08-events.md) emitted from all modules. The function returns an `abci.ResponseBeginBlock` which contains the aforementioned events. +* `EndBlock(ctx sdk.Context, req abci.RequestEndBlock)`: At the end of each block, this function is called from [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](05-beginblock-endblock.md) function of each modules implementing the `EndBlockAppModule` interface, in the order defined in `OrderEndBlockers`. It creates a child [context](../../develop/advanced-concepts/02-context.md) with an event manager to aggregate [events](../../develop/advanced-concepts/08-events.md) emitted from all modules. The function returns an `abci.ResponseEndBlock` which contains the aforementioned events, as well as validator set updates (if any). +* `Precommit(ctx sdk.Context)`: During [`Commit`](../../develop/advanced-concepts/00-baseapp.md#commit), this function is called from `BaseApp` immediately before the [`deliverState`](../../develop/advanced-concepts/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../develop/advanced-concepts/04-store.md#commitkvstore) and, in turn calls the `Precommit` function of each modules implementing the `HasPrecommit` interface, in the order defined in `OrderPrecommiters`. It creates a child [context](../../develop/advanced-concepts/02-context.md) where the underlying `CacheMultiStore` is that of the newly committed block's [`deliverState`](../../develop/advanced-concepts/00-baseapp.md#state-updates). +* `PrepareCheckState(ctx sdk.Context)`: During [`Commit`](../../develop/advanced-concepts/00-baseapp.md#commit), this function is called from `BaseApp` immediately after the [`deliverState`](../../develop/advanced-concepts/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../develop/advanced-concepts/04-store.md#commitmultistore) and, in turn calls the `PrepareCheckState` function of each module implementing the `HasPrepareCheckState` interface, in the order defined in `OrderPrepareCheckStaters`. It creates a child [context](../../develop/advanced-concepts/02-context.md) where the underlying `CacheMultiStore` is that of the next block's [`checkState`](../../develop/advanced-concepts/00-baseapp.md#state-updates). Writes to this state will be present in the [`checkState`](../../develop/advanced-concepts/00-baseapp.md#state-updates) of the next block, and therefore this method can be used to prepare the `checkState` for the next block. Here's an example of a concrete integration within an `simapp`: diff --git a/versioned_docs/version-0.47/integrate/building-modules/02-messages-and-queries.md b/versioned_docs/version-0.47/integrate/building-modules/02-messages-and-queries.md index 2021c7e96..f5df41a98 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/02-messages-and-queries.md +++ b/versioned_docs/version-0.47/integrate/building-modules/02-messages-and-queries.md @@ -12,19 +12,19 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](./01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: ## Messages -`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../core/01-transactions.md), which may contain one or more of them. +`Msg`s are objects whose end-goal is to trigger state-transitions. They are wrapped in [transactions](../../develop/advanced-concepts/01-transactions.md), which may contain one or more of them. -When a transaction is relayed from the underlying consensus engine to the Cosmos SDK application, it is first decoded by [`BaseApp`](../core/00-baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](./03-msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../basics/01-tx-lifecycle.md). +When a transaction is relayed from the underlying consensus engine to the Cosmos SDK application, it is first decoded by [`BaseApp`](../../develop/advanced-concepts/00-baseapp.md). Then, each message contained in the transaction is extracted and routed to the appropriate module via `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's [`Msg` service](03-msg-services.md). For a more detailed explanation of the lifecycle of a transaction, click [here](../../develop/high-level-concepts/01-tx-lifecycle.md). ### `Msg` Services -Defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../core/05-encoding.md#faq)). It must have an RPC service method defined for each message in the module. +Defining Protobuf `Msg` services is the recommended way to handle messages. A Protobuf `Msg` service should be created for each module, typically in `tx.proto` (see more info about [conventions and naming](../../develop/advanced-concepts/06-encoding.md#faq)). It must have an RPC service method defined for each message in the module. See an example of a `Msg` service definition from `x/bank` module: @@ -38,14 +38,14 @@ Each `Msg` service method must have exactly one argument, which must implement t rpc Send(MsgSend) returns (MsgSendResponse); ``` -`sdk.Msg` interface is a simplified version of the Amino `LegacyMsg` interface described [below](#legacy-amino-msgs) with only `ValidateBasic()` and `GetSigners()` methods. For backwards compatibility with [Amino `LegacyMsg`s](#legacy-amino-msgs), existing `LegacyMsg` types should be used as the request parameter for `service` RPC definitions. Newer `sdk.Msg` types, which only support `service` definitions, should use canonical `Msg...` name. +`sdk.Msg` interface is a simplified version of the Amino `LegacyMsg` interface described [below](#legacy-amino-legacymsg-s) with the `GetSigners()` method. For backwards compatibility with [Amino `LegacyMsg`s](#egacy-amino-legacymsg-s), existing `LegacyMsg` types should be used as the request parameter for `service` RPC definitions. Newer `sdk.Msg` types, which only support `service` definitions, should use canonical `Msg...` name. The Cosmos SDK uses Protobuf definitions to generate client and server code: -* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](./03-msg-services.md) documentation. +* `MsgServer` interface defines the server API for the `Msg` service and its implementation is described as part of the [`Msg` services](03-msg-services.md) documentation. * Structures are generated for all RPC request and response types. -A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). +A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](01-module-manager.md#appmodule). In order for clients (CLI and grpc-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](01-module-manager.md#appmodulebasic) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument. @@ -55,7 +55,7 @@ The following way of defining messages is deprecated and using [`Msg` services]( Amino `LegacyMsg`s can be defined as protobuf messages. The messages definition usually includes a list of parameters needed to process the message that will be provided by end-users when they want to create a new transaction containing said message. -A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](./09-module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: +A `LegacyMsg` is typically accompanied by a standard constructor function, that is called from one of the [module's interface](09-module-interfaces.md). `message`s also need to implement the `sdk.Msg` interface: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/tx_msg.go#L14-L26 @@ -63,9 +63,6 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/tx_msg.go#L14-L26 It extends `proto.Message` and contains the following methods: -* `Route() string`: Name of the route for this message. Typically all `message`s in a module have the same route, which is most often the module's name. -* `Type() string`: Type of the message, used primarily in [events](../core/08-events.md). This should return a message-specific `string`, typically the denomination of the message itself. -* [`ValidateBasic() error`](../basics/01-tx-lifecycle.md#ValidateBasic). * `GetSignBytes() []byte`: Return the canonical byte representation of the message. Used to generate a signature. * `GetSigners() []AccAddress`: Return the list of signers. The Cosmos SDK will make sure that each `message` contained in a transaction is signed by all the signers listed in the list returned by this method. @@ -81,7 +78,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/gov/types/v1/msgs.go#L12 ## Queries -A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `QueryRouter` so that it can be processed by the module's query service (./04-query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../basics/02-query-lifecycle.md). +A `query` is a request for information made by end-users of applications through an interface and processed by a full-node. A `query` is received by a full-node through its consensus engine and relayed to the application via the ABCI. It is then routed to the appropriate module via `BaseApp`'s `QueryRouter` so that it can be processed by the module's query service (./04-query-services.md). For a deeper look at the lifecycle of a `query`, click [here](../../develop/high-level-concepts/02-query-lifecycle.md). ### gRPC Queries @@ -95,7 +92,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/auth/v1beta1/ As `proto.Message`s, generated `Response` types implement by default `String()` method of [`fmt.Stringer`](https://pkg.go.dev/fmt#Stringer). -A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule). +A `RegisterQueryServer` method is also generated and should be used to register the module's query server in the `RegisterServices` method from the [`AppModule` interface](01-module-manager.md#appmodule). ### Legacy Queries @@ -107,15 +104,15 @@ queryCategory/queryRoute/queryType/arg1/arg2/... where: -* `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../core/00-baseapp.md#query). -* `queryRoute` is used by `BaseApp`'s [`queryRouter`](../core/00-baseapp.md#query-routing) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. -* `queryType` is used by the module's [`querier`](./04-query-services.md#legacy-queriers) to map the `query` to the appropriate `querier function` within the module. +* `queryCategory` is the category of the `query`, typically `custom` for module queries. It is used to differentiate between different kinds of queries within `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). +* `queryRoute` is used by `BaseApp`'s [`queryRouter`](../../develop/advanced-concepts/00-baseapp.md#grpc-query-router) to map the `query` to its module. Usually, `queryRoute` should be the name of the module. +* `queryType` is used by the module's [`querier`](04-query-services.md#query-services) to map the `query` to the appropriate `querier function` within the module. * `args` are the actual arguments needed to process the `query`. They are filled out by the end-user. Note that for bigger queries, you might prefer passing arguments in the `Data` field of the request `req` instead of the `path`. -The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](./09-module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: +The `path` for each `query` must be defined by the module developer in the module's [command-line interface file](09-module-interfaces.md#query-commands).Overall, there are 3 mains components module developers need to implement in order to make the subset of the state defined by their module queryable: -* A [`querier`](./04-query-services.md#legacy-queriers), to process the `query` once it has been [routed to the module](../core/00-baseapp.md#query-routing). -* [Query commands](./09-module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. +* A [`querier`](04-query-services.md#query-services), to process the `query` once it has been [routed to the module](../../develop/advanced-concepts/00-baseapp.md#grpc-query-router). +* [Query commands](09-module-interfaces.md#query-commands) in the module's CLI file, where the `path` for each `query` is specified. * `query` return types. Typically defined in a file `types/querier.go`, they specify the result type of each of the module's `queries`. These custom types must implement the `String()` method of [`fmt.Stringer`](https://pkg.go.dev/fmt#Stringer). ### Store Queries diff --git a/versioned_docs/version-0.47/integrate/building-modules/03-msg-services.md b/versioned_docs/version-0.47/integrate/building-modules/03-msg-services.md index b1e9a54d3..d9336b42c 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/03-msg-services.md +++ b/versioned_docs/version-0.47/integrate/building-modules/03-msg-services.md @@ -5,15 +5,15 @@ sidebar_position: 1 # `Msg` Services :::note Synopsis -A Protobuf `Msg` service processes [messages](./02-messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../core/00-baseapp.md#delivertx). +A Protobuf `Msg` service processes [messages](02-messages-and-queries.md#messages). Protobuf `Msg` services are specific to the module in which they are defined, and only process messages defined within the said module. They are called from `BaseApp` during [`DeliverTx`](../../develop/advanced-concepts/00-baseapp.md#delivertx). ::: :::note ### Pre-requisite Readings -* [Module Manager](./01-module-manager.md) -* [Messages and Queries](./02-messages-and-queries.md) +* [Module Manager](01-module-manager.md) +* [Messages and Queries](02-messages-and-queries.md) ::: @@ -29,7 +29,7 @@ Protobuf generates a `MsgServer` interface based on a definition of `Msg` servic https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/tx.pb.go#L550-L568 ``` -When possible, the existing module's [`Keeper`](./06-keeper.md) should implement `MsgServer`, otherwise a `msgServer` struct that embeds the `Keeper` can be created, typically in `./keeper/msg_server.go`: +When possible, the existing module's [`Keeper`](06-keeper.md) should implement `MsgServer`, otherwise a `msgServer` struct that embeds the `Keeper` can be created, typically in `./keeper/msg_server.go`: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/keeper/msg_server.go#L15-L17 @@ -43,10 +43,12 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/keeper/msg_server.g `sdk.Msg` processing usually follows these 3 steps: -### Validation +### Validation -Before a `msgServer` method is executed, the message's [`ValidateBasic()`](../basics/01-tx-lifecycle.md#ValidateBasic) method has already been called. Since `msg.ValidateBasic()` performs only the most basic checks, this stage must perform all other validation (both *stateful* and *stateless*) to make sure the `message` is valid. Checks performed in the `msgServer` method can be more expensive and the signer is charged gas for these operations. -For example, a `msgServer` method for a `transfer` message might check that the sending account has enough funds to actually perform the transfer. +The message server must perform all validation required (both *stateful* and *stateless*) to make sure the `message` is valid. +The `signer` is charged for the gas cost of this validation. + +For example, a `msgServer` method for a `transfer` message should check that the sending account has enough funds to actually perform the transfer. It is recommended to implement all validation checks in a separate function that passes state values as arguments. This implementation simplifies testing. As expected, expensive validation functions charge additional gas. Example: @@ -60,13 +62,18 @@ ValidateMsgA(msg MsgA, now Time, gm GasMeter) error { } ``` +:::warning +Previously, the `ValidateBasic` method was used to perform simple and stateless validation checks. +This way of validating is deprecated, this means the `msgServer` must perform all validation checks. +::: + ### State Transition -After the validation is successful, the `msgServer` method uses the [`keeper`](./06-keeper.md) functions to access the state and perform a state transition. +After the validation is successful, the `msgServer` method uses the [`keeper`](06-keeper.md) functions to access the state and perform a state transition. ### Events -Before returning, `msgServer` methods generally emit one or more [events](../core/08-events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: +Before returning, `msgServer` methods generally emit one or more [events](../../develop/advanced-concepts/08-events.md) by using the `EventManager` held in the `ctx`. Use the new `EmitTypedEvent` function that uses protobuf-based event types: ```go ctx.EventManager().EmitTypedEvent( @@ -85,7 +92,7 @@ ctx.EventManager().EmitEvent( ) ``` -These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../core/08-events.md) to learn more about events. +These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click [here](../../develop/advanced-concepts/08-events.md) to learn more about events. The invoked `msgServer` method returns a `proto.Message` response and an `error`. These return values are then wrapped into an `*sdk.Result` or an `error` using `sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error)`: @@ -105,7 +112,7 @@ This diagram shows a typical structure of a Protobuf `Msg` service, and how the ## Telemetry -New [telemetry metrics](../core/09-telemetry.md) can be created from `msgServer` methods when handling messages. +New [telemetry metrics](../../develop/advanced-concepts/11-telemetry.md) can be created from `msgServer` methods when handling messages. This is an example from the `x/auth/vesting` module: diff --git a/versioned_docs/version-0.47/integrate/building-modules/04-query-services.md b/versioned_docs/version-0.47/integrate/building-modules/04-query-services.md index cedeb0928..37576c02b 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/04-query-services.md +++ b/versioned_docs/version-0.47/integrate/building-modules/04-query-services.md @@ -5,15 +5,15 @@ sidebar_position: 1 # Query Services :::note Synopsis -A Protobuf Query service processes [`queries`](./02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../core/00-baseapp.md#query). +A Protobuf Query service processes [`queries`](02-messages-and-queries.md#queries). Query services are specific to the module in which they are defined, and only process `queries` defined within said module. They are called from `BaseApp`'s [`Query` method](../../develop/advanced-concepts/00-baseapp.md#query). ::: :::note ### Pre-requisite Readings -* [Module Manager](./01-module-manager.md) -* [Messages and Queries](./02-messages-and-queries.md) +* [Module Manager](01-module-manager.md) +* [Messages and Queries](02-messages-and-queries.md) ::: diff --git a/versioned_docs/version-0.47/integrate/building-modules/05-beginblock-endblock.md b/versioned_docs/version-0.47/integrate/building-modules/05-beginblock-endblock.md index 4cfdda370..df1b63705 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/05-beginblock-endblock.md +++ b/versioned_docs/version-0.47/integrate/building-modules/05-beginblock-endblock.md @@ -5,14 +5,14 @@ sidebar_position: 1 # BeginBlocker and EndBlocker :::note Synopsis -`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../core/00-baseapp.md#beginblock) and [`EndBlock`](../core/00-baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. +`BeginBlocker` and `EndBlocker` are optional methods module developers can implement in their module. They will be triggered at the beginning and at the end of each block respectively, when the [`BeginBlock`](../../develop/advanced-concepts/00-baseapp.md#beginblock) and [`EndBlock`](../../develop/advanced-concepts/00-baseapp.md#endblock) ABCI messages are received from the underlying consensus engine. ::: :::note ### Pre-requisite Readings -* [Module Manager](./01-module-manager.md) +* [Module Manager](01-module-manager.md) ::: @@ -20,17 +20,17 @@ sidebar_position: 1 `BeginBlocker` and `EndBlocker` are a way for module developers to add automatic execution of logic to their module. This is a powerful tool that should be used carefully, as complex automatic functions can slow down or even halt the chain. -When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`BeginBlockAppModule` and `BeginBlockAppModule` interfaces](./01-module-manager.md#appmodule). This means either can be left-out if not required. The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. +When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`BeginBlockAppModule` and `BeginBlockAppModule` interfaces](01-module-manager.md#appmodule). This means either can be left-out if not required. The `BeginBlock` and `EndBlock` methods of the interface implemented in `module.go` generally defer to `BeginBlocker` and `EndBlocker` methods respectively, which are usually implemented in `abci.go`. -The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./03-msg-services.md): +The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](03-msg-services.md): -* They generally use the [`keeper`](./06-keeper.md) and [`ctx`](../core/02-context.md) to retrieve information about the latest state. +* They generally use the [`keeper`](06-keeper.md) and [`ctx`](../../develop/advanced-concepts/02-context.md) to retrieve information about the latest state. * If needed, they use the `keeper` and `ctx` to trigger state-transitions. -* If needed, they can emit [`events`](../core/08-events.md) via the `ctx`'s `EventManager`. +* If needed, they can emit [`events`](../../develop/advanced-concepts/08-events.md) via the `ctx`'s `EventManager`. A specificity of the `EndBlocker` is that it can return validator updates to the underlying consensus engine in the form of an [`[]abci.ValidatorUpdates`](https://docs.cometbft.com/v0.37/spec/abci/abci++_methods#endblock). This is the preferred way to implement custom validator changes. -It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./01-module-manager.md#manager). +It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](01-module-manager.md#manager). See an example implementation of `BeginBlocker` from the `distribution` module: @@ -43,3 +43,5 @@ and an example implementation of `EndBlocker` from the `staking` module: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/abci.go#L22-L27 ``` + + diff --git a/versioned_docs/version-0.47/integrate/building-modules/06-keeper.md b/versioned_docs/version-0.47/integrate/building-modules/06-keeper.md index 946eff6ff..39305136f 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/06-keeper.md +++ b/versioned_docs/version-0.47/integrate/building-modules/06-keeper.md @@ -12,7 +12,7 @@ sidebar_position: 1 ### Pre-requisite Readings -* [Introduction to Cosmos SDK Modules](./01-intro.md) +* [Introduction to Cosmos SDK Modules](00-intro.md) ::: @@ -20,9 +20,9 @@ sidebar_position: 1 The Cosmos SDK is a framework that makes it easy for developers to build complex decentralized applications from scratch, mainly by composing modules together. As the ecosystem of open-source modules for the Cosmos SDK expands, it will become increasingly likely that some of these modules contain vulnerabilities, as a result of the negligence or malice of their developer. -The Cosmos SDK adopts an [object-capabilities-based approach](../core/10-ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be considered quite literally to be the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../core/04-store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). +The Cosmos SDK adopts an [object-capabilities-based approach](../../develop/advanced-concepts/10-ocap.md) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be considered quite literally to be the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](../../develop/advanced-concepts/04-store.md#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s). -The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../basics/00-app-anatomy.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. +The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers. ## Type Definition @@ -49,14 +49,14 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/keeper/keeper.go Let us go through the different parameters: * An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself. -* `storeKey`s grant access to the store(s) of the [multistore](../core/04-store.md) managed by the module. They should always remain unexposed to external modules. -* `cdc` is the [codec](../core/05-encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. The authority listed is a module account or user account that has the right to change module level parameters. Previously this was handled by the param module, which has been deprecated. +* `storeKey`s grant access to the store(s) of the [multistore](../../develop/advanced-concepts/04-store.md) managed by the module. They should always remain unexposed to external modules. +* `cdc` is the [codec](../../develop/advanced-concepts/06-encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. The authority listed is a module account or user account that has the right to change module level parameters. Previously this was handled by the param module, which has been deprecated. -Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../basics/00-app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. +Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../../develop/high-level-concepts/00-overview-app.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. ## Implementing Methods -`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed via the `ValidateBasic()` method of the [`message`](./02-messages-and-queries.md#messages) and the [`Msg` server](./03-msg-services.md) when `keeper`s' methods are called. +`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed by the [`Msg` server](03-msg-services.md) when `keeper`s' methods are called. Typically, a *getter* method will have the following signature @@ -84,7 +84,7 @@ and the method will go through the following steps: For more, see an example of `keeper`'s [methods implementation from the `staking` module](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/keeper/keeper.go). -The [module `KVStore`](../core/04-store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. +The [module `KVStore`](../../develop/advanced-concepts/04-store.md#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys. This is an example from the `auth` module to iterate accounts: diff --git a/versioned_docs/version-0.47/integrate/building-modules/07-invariants.md b/versioned_docs/version-0.47/integrate/building-modules/07-invariants.md index 4c53169d4..f2cf9b964 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/07-invariants.md +++ b/versioned_docs/version-0.47/integrate/building-modules/07-invariants.md @@ -12,7 +12,7 @@ An invariant is a property of the application that should always be true. In the ### Pre-requisite Readings -* [Keepers](./06-keeper.md) +* [Keepers](06-keeper.md) ::: @@ -57,7 +57,7 @@ func AllInvariants(k Keeper) sdk.Invariant { } ``` -Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](./01-module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): +Finally, module developers need to implement the `RegisterInvariants` method as part of the [`AppModule` interface](01-module-manager.md#appmodule). Indeed, the `RegisterInvariants` method of the module, implemented in the `module/module.go` file, typically only defers the call to a `RegisterInvariants` method implemented in the `keeper/invariants.go` file. The `RegisterInvariants` method registers a route for each `Invariant` function in the [`InvariantRegistry`](#invariant-registry): ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/keeper/invariants.go#L12-L22 @@ -81,9 +81,9 @@ Typically, this interface is implemented in the `keeper` of a specific module. T https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/crisis/keeper/keeper.go#L57-L61 ``` -The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../basics/00-app-anatomy.md#constructor-function). +The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). -`Invariant`s can be checked manually via [`message`s](./02-messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: +`Invariant`s can be checked manually via [`message`s](02-messages-and-queries.md), but most often they are checked automatically at the end of each block. Here is an example from the `crisis` module: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/crisis/abci.go#L12-L21 diff --git a/versioned_docs/version-0.47/integrate/building-modules/08-genesis.md b/versioned_docs/version-0.47/integrate/building-modules/08-genesis.md index a63c8b119..6337f3790 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/08-genesis.md +++ b/versioned_docs/version-0.47/integrate/building-modules/08-genesis.md @@ -12,14 +12,14 @@ Modules generally handle a subset of the state and, as such, they need to define ### Pre-requisite Readings -* [Module Manager](./01-module-manager.md) -* [Keepers](./06-keeper.md) +* [Module Manager](01-module-manager.md) +* [Keepers](06-keeper.md) ::: ## Type Definition -The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../core/05-encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. +The subset of the genesis state defined from a given module is generally defined in a `genesis.proto` file ([more info](../../develop/advanced-concepts/06-encoding.md#gogoproto) on how to define protobuf messages). The struct defining the module's subset of the genesis state is usually called `GenesisState` and contains all the module-related values that need to be initialized during the genesis process. See an example of `GenesisState` protobuf message definition from the `auth` module: @@ -47,13 +47,13 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/types/genesis.go#L6 ## Other Genesis Methods -Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](./01-module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). +Other than the methods related directly to `GenesisState`, module developers are expected to implement two other methods as part of the [`AppModuleGenesis` interface](01-module-manager.md#appmodulegenesis) (only if the module needs to initialize a subset of state in genesis). These methods are [`InitGenesis`](#initgenesis) and [`ExportGenesis`](#exportgenesis). ### `InitGenesis` -The `InitGenesis` method is executed during [`InitChain`](../core/00-baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](./06-keeper.md) setter function on each parameter within the `GenesisState`. +The `InitGenesis` method is executed during [`InitChain`](../../develop/advanced-concepts/00-baseapp.md#initchain) when the application is first started. Given a `GenesisState`, it initializes the subset of the state managed by the module by using the module's [`keeper`](06-keeper.md) setter function on each parameter within the `GenesisState`. -The [module manager](./01-module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../basics/00-app-anatomy.md#constructor-function). +The [module manager](01-module-manager.md#manager) of the application is responsible for calling the `InitGenesis` method of each of the application's modules in order. This order is set by the application developer via the manager's `SetOrderGenesisMethod`, which is called in the [application's constructor function](../../develop/high-level-concepts/00-overview-app.md#constructor-function). See an example of `InitGenesis` from the `auth` module: @@ -70,3 +70,11 @@ See an example of `ExportGenesis` from the `auth` module. ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/keeper/genesis.go#L37-L49 ``` + +### GenesisTxHandler + +`GenesisTxHandler` is a way for modules to submit state transitions prior to the first block. This is used by `x/genutil` to submit the genesis transactions for the validators to be added to staking. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/advanced-concepts/genesis/txhandler.go#L3-L6 +``` diff --git a/versioned_docs/version-0.47/integrate/building-modules/09-module-interfaces.md b/versioned_docs/version-0.47/integrate/building-modules/09-module-interfaces.md index 12f290183..d706df9b2 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/09-module-interfaces.md +++ b/versioned_docs/version-0.47/integrate/building-modules/09-module-interfaces.md @@ -12,17 +12,17 @@ This document details how to build CLI and REST interfaces for a module. Example ### Pre-requisite Readings -* [Building Modules Intro](./01-intro.md) +* [Building Modules Intro](00-intro.md) ::: ## CLI -One of the main interfaces for an application is the [command-line interface](../core/07-cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](./02-messages-and-queries.md#messages) wrapped in transactions and [**queries**](./02-messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. +One of the main interfaces for an application is the [command-line interface](../../develop/advanced-concepts/07-cli.md). This entrypoint adds commands from the application's modules enabling end-users to create [**messages**](02-messages-and-queries.md#messages) wrapped in transactions and [**queries**](02-messages-and-queries.md#queries). The CLI files are typically found in the module's `./client/cli` folder. ### Transaction Commands -In order to create messages that trigger state changes, end-users must create [transactions](../core/01-transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. +In order to create messages that trigger state changes, end-users must create [transactions](../../develop/advanced-concepts/01-transactions.md) that wrap and deliver the messages. A transaction command creates a transaction that includes one or more messages. Transaction commands typically have their own `tx.go` file that lives within the module's `./client/cli` folder. The commands are specified in getter functions and the name of the function should include the name of the command. @@ -43,7 +43,7 @@ In general, the getter function does the following: * **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new transaction. * The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientTxContext(cmd)`. The `clientCtx` contains information relevant to transaction handling, including information about the user. In this example, the `clientCtx` is used to retrieve the address of the sender by calling `clientCtx.GetFromAddress()`. * If applicable, the command's arguments are parsed. In this example, the arguments `[to_address]` and `[amount]` are both parsed. - * A [message](./02-messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call [`msg.ValidateBasic()`](../basics/01-tx-lifecycle.md#ValidateBasic) and other validation methods before broadcasting the message. + * A [message](02-messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call, if possible, the necessary [message validation methods](Validation) before broadcasting the message. * Depending on what the user wants, the transaction is either generated offline or signed and broadcasted to the preconfigured node using `tx.GenerateOrBroadcastTxCLI(clientCtx, flags, msg)`. * **Adds transaction flags:** All transaction commands must add a set of transaction [flags](#flags). The transaction flags are used to collect additional information from the user (e.g. the amount of fees the user is willing to pay). The transaction flags are added to the constructed command using `AddTxFlagsToCmd(cmd)`. * **Returns the command:** Finally, the transaction command is returned. @@ -62,7 +62,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/module.go#L79-L82 ### Query Commands -[Queries](./02-messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: +[Queries](02-messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/client/cli/query.go#L86-L128 @@ -79,7 +79,7 @@ In general, the getter function does the following: * **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new query. * The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientQueryContext(cmd)`. The `clientCtx` contains information relevant to query handling. * If applicable, the command's arguments are parsed. In this example, the argument `[address]` is parsed. - * A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./02-messages-and-queries.md#grpc-queries). + * A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](02-messages-and-queries.md#grpc-queries). * The `clientCtx.PrintProto` method is used to format the `proto.Message` object so that the results can be printed back to the user. * **Adds query flags:** All query commands must add a set of query [flags](#flags). The query flags are added to the constructed command using `AddQueryFlagsToCmd(cmd)`. * **Returns the command:** Finally, the query command is returned. @@ -98,7 +98,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/module.go#L84-L87 ### Flags -[Flags](../core/07-cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../basics/04-gas-fees.md) and gas prices for their transactions. +[Flags](../../develop/advanced-concepts/07-cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../../develop/high-level-concepts/04-gas-fees.md) and gas prices for their transactions. Flags that are specific to a module are typically created in a `flags.go` file in the module's `./client/cli` folder. When creating a flag, developers set the value type, the name of the flag, the default value, and a description about the flag. Developers also have the option to mark flags as _required_ so that an error is thrown if the user does not include a value for the flag. @@ -156,6 +156,6 @@ Modules that want to expose REST queries should add `google.api.http` annotation https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/auth/v1beta1/query.proto#L14-L89 ``` -gRPC gateway is started in-process along with the application and CometBFT. It can be enabled or disabled by setting gRPC Configuration `enable` in [`app.toml`](../run-node/02-interact-node.md#configuring-the-node-using-apptoml). +gRPC gateway is started in-process along with the application and CometBFT. It can be enabled or disabled by setting gRPC Configuration `enable` in [`app.toml`](../../user/run-node/02-interact-node.md#configuring-the-node-using-apptoml). -The Cosmos SDK provides a command for generating [Swagger](https://swagger.io/) documentation (`protoc-gen-swagger`). Setting `swagger` in [`app.toml`](../run-node/02-interact-node.md#configuring-the-node-using-apptoml) defines if swagger documentation should be automatically registered. +The Cosmos SDK provides a command for generating [Swagger](https://swagger.io/) documentation (`protoc-gen-swagger`). Setting `swagger` in [`app.toml`](../../user/run-node/02-interact-node.md#configuring-the-node-using-apptoml) defines if swagger documentation should be automatically registered. diff --git a/versioned_docs/version-0.47/integrate/building-modules/11-structure.md b/versioned_docs/version-0.47/integrate/building-modules/11-structure.md index 255893257..22930ee42 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/11-structure.md +++ b/versioned_docs/version-0.47/integrate/building-modules/11-structure.md @@ -15,13 +15,13 @@ A typical Cosmos SDK module can be structured as follows: ```shell proto └── {project_name} - └── {module_name} - └── {proto_version} - ├── {module_name}.proto - ├── event.proto - ├── genesis.proto - ├── query.proto - └── tx.proto +    └── {module_name} +    └── {proto_version} +       ├── {module_name}.proto +       ├── event.proto +       ├── genesis.proto +       ├── query.proto +       └── tx.proto ``` * `{module_name}.proto`: The module's common message type definitions. @@ -33,33 +33,33 @@ proto ```shell x/{module_name} ├── client -│ ├── cli -│ │ ├── query.go -│ │ └── tx.go -│ └── testutil -│ ├── cli_test.go -│ └── suite.go +│   ├── cli +│   │ ├── query.go +│   │   └── tx.go +│   └── testutil +│   ├── cli_test.go +│   └── suite.go ├── exported -│ └── exported.go +│   └── exported.go ├── keeper -│ ├── genesis.go -│ ├── grpc_query.go -│ ├── hooks.go -│ ├── invariants.go -│ ├── keeper.go -│ ├── keys.go -│ ├── msg_server.go -│ └── querier.go +│   ├── genesis.go +│   ├── grpc_query.go +│   ├── hooks.go +│   ├── invariants.go +│   ├── keeper.go +│   ├── keys.go +│   ├── msg_server.go +│   └── querier.go ├── module -│ └── module.go -│ └── abci.go +│   └── module.go +│   └── abci.go +│   └── autocli.go ├── simulation -│ ├── decoder.go -│ ├── genesis.go -│ ├── operations.go -│ └── params.go +│   ├── decoder.go +│   ├── genesis.go +│   ├── operations.go +│   └── params.go ├── {module_name}.pb.go -├── autocli.go ├── codec.go ├── errors.go ├── events.go @@ -72,24 +72,24 @@ x/{module_name} ├── params.go ├── query.pb.go ├── tx.pb.go -└── README.md +└── 05-depinject.md ``` -* `client/`: The module's CLI client functionality implementation and the module's integration testing suite. +* `client/`: The module's CLI client functionality implementation and the module's CLI testing suite. * `exported/`: The module's exported types - typically interface types. If a module relies on keepers from another module, it is expected to receive the keepers as interface contracts through the `expected_keepers.go` file (see below) in order to avoid a direct dependency on the module implementing the keepers. However, these interface contracts can define methods that operate on and/or return types that are specific to the module that is implementing the keepers and this is where `exported/` comes into play. The interface types that are defined in `exported/` use canonical types, allowing for the module to receive the keepers as interface contracts through the `expected_keepers.go` file. This pattern allows for code to remain DRY and also alleviates import cycle chaos. * `keeper/`: The module's `Keeper` and `MsgServer` implementation. * `module/`: The module's `AppModule` and `AppModuleBasic` implementation. * `abci.go`: The module's `BeginBlocker` and `EndBlocker` implementations (this file is only required if `BeginBlocker` and/or `EndBlocker` need to be defined). -* `simulation/`: The module's [simulation](./14-simulator.md) package defines functions used by the blockchain simulator application (`simapp`). -* `REAMDE.md`: The module's specification documents outlining important concepts, state storage structure, and message and event type definitions. Learn more how to write module specs in the [spec guidelines](../spec/SPEC-SPEC.md). + * `autocli.go`: The module [autocli](../tooling/03-autocli.md) options. +* `simulation/`: The module's [simulation](14-simulator.md) package defines functions used by the blockchain simulator application (`simapp`). +* `REAMDE.md`: The module's specification documents outlining important concepts, state storage structure, and message and event type definitions. Learn more how to write module specs in the [spec guidelines](../spec/SPEC_MODULE.md). * The root directory includes type definitions for messages, events, and genesis state, including the type definitions generated by Protocol Buffers. - * `autocli.go`: The module [autocli](./10-autocli.md) options. * `codec.go`: The module's registry methods for interface types. * `errors.go`: The module's sentinel errors. * `events.go`: The module's event types and constructors. - * `expected_keepers.go`: The module's [expected keeper](./06-keeper.md#type-definition) interfaces. + * `expected_keepers.go`: The module's [expected keeper](06-keeper.md#type-definition) interfaces. * `genesis.go`: The module's genesis state methods and helper functions. * `keys.go`: The module's store keys and associated helper functions. * `msgs.go`: The module's message type definitions and associated methods. * `params.go`: The module's parameter type definitions and associated methods. - * `*.pb.go`: The module's type definitions generated by Protocol Buffers (as defined in the respective `*.proto` files above). \ No newline at end of file + * `*.pb.go`: The module's type definitions generated by Protocol Buffers (as defined in the respective `*.proto` files above). diff --git a/versioned_docs/version-0.47/integrate/building-modules/13-upgrade.md b/versioned_docs/version-0.47/integrate/building-modules/13-upgrade.md index 18484c68c..3cc63cfe7 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/13-upgrade.md +++ b/versioned_docs/version-0.47/integrate/building-modules/13-upgrade.md @@ -5,14 +5,14 @@ sidebar_position: 1 # Upgrading Modules :::note Synopsis -[In-Place Store Migrations](../core/15-upgrade.md) allow your modules to upgrade to new versions that include breaking changes. This document outlines how to build modules to take advantage of this functionality. +[In-Place Store Migrations](../../develop/advanced-concepts/16-upgrade.md) allow your modules to upgrade to new versions that include breaking changes. This document outlines how to build modules to take advantage of this functionality. ::: :::note ### Pre-requisite Readings -* [In-Place Store Migration](../core/15-upgrade.md) +* [In-Place Store Migration](../../develop/advanced-concepts/16-upgrade.md) ::: diff --git a/versioned_docs/version-0.47/integrate/building-modules/14-simulator.md b/versioned_docs/version-0.47/integrate/building-modules/14-simulator.md index d3483cec6..1bd7667eb 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/14-simulator.md +++ b/versioned_docs/version-0.47/integrate/building-modules/14-simulator.md @@ -5,9 +5,10 @@ sidebar_position: 1 # Module Simulation :::note + ### Pre-requisite Readings -* [Cosmos Blockchain Simulator](../core/12-simulation.md) +* [Cosmos Blockchain Simulator](../../develop/advanced-concepts/13-simulation.md) ::: ## Synopsis @@ -63,7 +64,7 @@ Operations are one of the crucial parts of the Cosmos SDK simulation. They are t (`Msg`) that are simulated with random field values. The sender of the operation is also assigned randomly. -Operations on the simulation are simulated using the full [transaction cycle](../core/01-transactions.md) of a +Operations on the simulation are simulated using the full [transaction cycle](../../develop/advanced-concepts/01-transactions.md) of a `ABCI` application that exposes the `BaseApp`. Shown below is how weights are set: diff --git a/versioned_docs/version-0.47/integrate/building-modules/15-depinject.md b/versioned_docs/version-0.47/integrate/building-modules/15-depinject.md index 96dd5dc39..9a51850d0 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/15-depinject.md +++ b/versioned_docs/version-0.47/integrate/building-modules/15-depinject.md @@ -2,17 +2,17 @@ sidebar_position: 1 --- -# Dependency Injection +# Modules depinject-ready :::note ### Pre-requisite Readings -* [Cosmos SDK Dependency Injection Framework](../tooling/02-depinject.md) +* [Depinject Documentation](../libraries/01-depinject.md) ::: -[`depinject`](../tooling/02-depinject.md) is used to wire any module in `app.go`. +[`depinject`](../libraries/01-depinject.md) is used to wire any module in `app.go`. All core modules are already configured to support dependency injection. To work with `depinject` a module must define its configuration and requirements so that `depinject` can provide the right dependencies. @@ -121,6 +121,6 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/module/module.go#L The module is now ready to be used with `depinject` by a chain developer. -## App Wiring +## Integrate in an application The App Wiring is done in `app_config.go` / `app.yaml` and `app_v2.go` and is explained in detail in the [overview of `app_v2.go`](../building-apps/01-app-go-v2.md). diff --git a/versioned_docs/version-0.47/integrate/building-modules/16-testing.md b/versioned_docs/version-0.47/integrate/building-modules/16-testing.md index 7de77ec89..b76f626da 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/16-testing.md +++ b/versioned_docs/version-0.47/integrate/building-modules/16-testing.md @@ -57,34 +57,16 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/gov/keeper/keeper_test.g Integration tests are at the second level of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html). In the SDK, we locate our integration tests under [`/tests/integrations`](https://github.com/cosmos/cosmos-sdk/tree/main/tests/integration). -The goal of these integration tests is to test a component with a minimal application (i.e. not `simapp`). The minimal application is defined with the help of [`depinject`](../tooling/02-depinject.md) – the SDK dependency injection framework, and includes all necessary modules to test the component. With the helps of the SDK testing package, we can easily create a minimal application and start the application with a set of genesis transactions: . +The goal of these integration tests is to test how a component interacts with other dependencies. Compared to unit tests, integration tests do not mock dependencies. Instead, they use the direct dependencies of the component. This differs as well from end-to-end tests, which test the component with a full application. -### Example - -Here, we will walkthrough the integration tests of the `x/distribution` module. The `x/distribution` module has, in addition to keeper unit tests, integration tests that test the `x/distribution` module with a minimal application. This is expected as you may want to test the `x/distribution` module with actual application logic, instead of only mocked dependencies. - -For creating a minimal application, we use [`simtestutil.Setup`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/testutil/sims/app_helpers.go#L95-L99) and an [`AppConfig`](../tooling/02-depinject.md) of the `x/distribution` minimal dependencies. - -For instance, the `AppConfig` of `x/distribution` is defined as: - -* https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/distribution/testutil/app_config.go - -This is a stripped down version of the `simapp` `AppConfig`: - -* https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app_config.go - -:::note -You can as well use the `AppConfig` `configurator` for creating an `AppConfig` [inline](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/slashing/app_test.go#L54-L62). There no difference between those two ways, use whichever you prefer. -::: +Integration tests interact with the tested module via the defined `Msg` and `Query` services. The result of the test can be verified by checking the state of the application, by checking the emitted events or the response. It is adviced to combine two of these methods to verify the result of the test. -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/tests/integration/distribution/keeper/keeper_test.go#L28-L33 -``` +The SDK provides small helpers for quickly setting up an integration tests. These helpers can be found at . -Now the types are injected and we can use them for our tests: +### Example ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/tests/integration/distribution/keeper/keeper_test.go#L21-L53 +https://github.com/cosmos/cosmos-sdk/blob/29e22b3bdb05353555c8e0b269311bbff7b8deca/testutil/integration/example_test.go#L22-L89 ``` ## Deterministic and Regression tests @@ -104,7 +86,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/tests/integration/bank/kee ## Simulations -Simulations uses as well a minimal application, built with [`depinject`](../tooling/02-depinject.md): +Simulations uses as well a minimal application, built with [`depinject`](../libraries/01-depinject.md): + +:::note +You can as well use the `AppConfig` `configurator` for creating an `AppConfig` [inline](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/slashing/app_test.go#L54-L62). There is no difference between those two ways, use whichever you prefer. +::: Following is an example for `x/gov/` simulations: @@ -121,6 +107,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/gov/simulation/operation End-to-end tests are at the top of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html). They must test the whole application flow, from the user perspective (for instance, CLI tests). They are located under [`/tests/e2e`](https://github.com/cosmos/cosmos-sdk/tree/main/tests/e2e). + For that, the SDK is using `simapp` but you should use your own application (`appd`). Here are some examples: @@ -132,11 +119,6 @@ Here are some examples: The SDK is in the process of creating its E2E tests, as defined in [ADR-59](https://docs.cosmos.network/main/architecture/adr-059-test-scopes.html). This page will eventually be updated with better examples. ::: -## Summary +## Learn More -| Scope | App Fixture | Mocks? | -| ----------- | ----------- | ------ | -| Unit | None | Yes | -| Integration | `depinject` | Some | -| Simulation | `depinject` | No | -| E2E | `appd` | No | +Learn more about testing scope in [ADR-59](https://docs.cosmos.network/main/architecture/adr-059-test-scopes.html). diff --git a/versioned_docs/version-0.47/integrate/building-modules/_category_.json b/versioned_docs/version-0.47/integrate/building-modules/_category_.json index 8dc3f9a94..2d50f8b3e 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/_category_.json +++ b/versioned_docs/version-0.47/integrate/building-modules/_category_.json @@ -1,5 +1,5 @@ { "label": "Building Modules", - "position": 3, + "position": 1, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/building-modules/transaction_flow.svg b/versioned_docs/version-0.47/integrate/building-modules/transaction_flow.svg new file mode 100644 index 000000000..1ae962de3 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/building-modules/transaction_flow.svg @@ -0,0 +1,48 @@ +UserUserbaseAppbaseApprouterrouterhandlerhandlermsgServermsgServerkeeperkeeperContext.EventManagerContext.EventManagerTransaction Type<Tx>Route(ctx, msgRoute)handlerMsg<Tx>(Context, Msg(...))<Tx>(Context, Msg)alt[addresses invalid, denominations wrong, etc.]errorperform action, update contextresults, error codeEmit relevant eventsmaybe wrap results in more structureresult, error coderesults, error code \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/libraries/01-depinject.md b/versioned_docs/version-0.47/integrate/libraries/01-depinject.md new file mode 100644 index 000000000..258e1e0b6 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/libraries/01-depinject.md @@ -0,0 +1,187 @@ +--- +sidebar_position: 1 +--- + +# Depinject + +> **DISCLAIMER**: This is a **beta** package. The SDK team is actively working on this feature and we are looking for feedback from the community. Please try it out and let us know what you think. + +## Overview + +`depinject` is a dependency injection (DI) framework for the Cosmos SDK, designed to streamline the process of building and configuring blockchain applications. It works in conjunction with the `core/appconfig` module to replace the majority of boilerplate code in `app.go` with a configuration file in Go, YAML, or JSON format. + +`depinject` is particularly useful for developing blockchain applications: + +* With multiple interdependent components, modules, or services. Helping manage their dependencies effectively. +* That require decoupling of these components, making it easier to test, modify, or replace individual parts without affecting the entire system. +* That are wanting to simplify the setup and initialisation of modules and their dependencies by reducing boilerplate code and automating dependency management. + +By using `depinject`, developers can achieve: + +* Cleaner and more organised code. +* Improved modularity and maintainability. +* A more maintainable and modular structure for their blockchain applications, ultimately enhancing development velocity and code quality. + +* [Go Doc](https://pkg.go.dev/cosmossdk.io/depinject) + +## Usage + +The `depinject` framework, based on dependency injection concepts, streamlines the management of dependencies within your blockchain application using its Configuration API. This API offers a set of functions and methods to create easy to use configurations, making it simple to define, modify, and access dependencies and their relationships. + +A core component of the [Configuration API](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/depinject#Config) is the `Provide` function, which allows you to register provider functions that supply dependencies. Inspired by constructor injection, these provider functions form the basis of the dependency tree, enabling the management and resolution of dependencies in a structured and maintainable manner. Additionally, `depinject` supports interface types as inputs to provider functions, offering flexibility and decoupling between components, similar to interface injection concepts. + +By leveraging `depinject` and its Configuration API, you can efficiently handle dependencies in your blockchain application, ensuring a clean, modular, and well-organised codebase. + +Example: + +```go +package main + +import ( + "fmt" + + "cosmossdk.io/depinject" +) + +type AnotherInt int + +func main() { + var ( + x int + y AnotherInt + ) + + fmt.Printf("Before (%v, %v)\n", x, y) + depinject.Inject( + depinject.Provide( + func() int { return 1 }, + func() AnotherInt { return AnotherInt(2) }, + ), + &x, + &y, + ) + fmt.Printf("After (%v, %v)\n", x, y) +} +``` + +In this example, `depinject.Provide` registers two provider functions that return `int` and `AnotherInt` values. The `depinject.Inject` function is then used to inject these values into the variables `x` and `y`. + +Provider functions serve as the basis for the dependency tree. They are analysed to identify their inputs as dependencies and their outputs as dependents. These dependents can either be used by another provider function or be stored outside the DI container (e.g., `&x` and `&y` in the example above). + +### Interface type resolution + +`depinject` supports the use of interface types as inputs to provider functions, which helps decouple dependencies between modules. This approach is particularly useful for managing complex systems with multiple modules, such as the Cosmos SDK, where dependencies need to be flexible and maintainable. + +For example, `x/bank` expects an [AccountKeeper](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/x/bank/types#AccountKeeper) interface as [input to ProvideModule](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/module.go#L208-L260). `SimApp` uses the implementation in `x/auth`, but the modular design allows for easy changes to the implementation if needed. + +Consider the following example: + +```go +package duck + +type Duck interface { + quack() +} + +type AlsoDuck interface { + quack() +} + +type Mallard struct{} +type Canvasback struct{} + +func (duck Mallard) quack() {} +func (duck Canvasback) quack() {} + +type Pond struct { + Duck AlsoDuck +} +``` + +In this example, there's a `Pond` struct that has a `Duck` field of type `AlsoDuck`. The `depinject` framework can automatically resolve the appropriate implementation when there's only one available, as shown below: + +```go +var pond Pond + +depinject.Inject( + depinject.Provide( + func() Mallard { return Mallard{} }, + func(duck Duck) Pond { + return Pond{Duck: duck} + }), + &pond) +``` + +This code snippet results in the `Duck` field of `Pond` being implicitly bound to the `Mallard` implementation because it's the only implementation of the `Duck` interface in the container. + +However, if there are multiple implementations of the `Duck` interface, as in the following example, you'll encounter an error: + +```go +var pond Pond + +depinject.Inject( + depinject.Provide( + func() Mallard { return Mallard{} }, + func() Canvasback { return Canvasback{} }, + func(duck Duck) Pond { + return Pond{Duck: duck} + }), + &pond) +``` + +A specific binding preference for `Duck` is required. + +#### `BindInterface` API + +In the above situation registering a binding for a given interface binding may look like: + +```go +depinject.Inject( + depinject.Configs( + depinject.BindInterface( + "duck.Duck", + "duck.Mallard"), + depinject.Provide( + func() Mallard { return Mallard{} }, + func() Canvasback { return Canvasback{} }, + func(duck Duck) APond { + return Pond{Duck: duck} + })), + &pond) +``` + +Now `depinject` has enough information to provide `Mallard` as an input to `APond`. + +### Full example in real app + +:::warning +When using `depinject.Inject`, the injected types must be pointers. +::: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app_v2.go#L219-L244 +``` + +## Debugging + +Issues with resolving dependencies in the container can be done with logs and [Graphviz](https://graphviz.org) renderings of the container tree. +By default, whenever there is an error, logs will be printed to stderr and a rendering of the dependency graph in Graphviz DOT format will be saved to `debug_container.dot`. + +Here is an example Graphviz rendering of a successful build of a dependency graph: +![Graphviz Example](https://raw.githubusercontent.com/cosmos/cosmos-sdk/ff39d243d421442b400befcd959ec3ccd2525154/depinject/testdata/example.svg) + +Rectangles represent functions, ovals represent types, rounded rectangles represent modules and the single hexagon +represents the function which called `Build`. Black-colored shapes mark functions and types that were called/resolved +without an error. Gray-colored nodes mark functions and types that could have been called/resolved in the container but +were left unused. + +Here is an example Graphviz rendering of a dependency graph build which failed: +![Graphviz Error Example](https://raw.githubusercontent.com/cosmos/cosmos-sdk/ff39d243d421442b400befcd959ec3ccd2525154/depinject/testdata/example_error.svg) + +Graphviz DOT files can be converted into SVG's for viewing in a web browser using the `dot` command-line tool, ex: + +```txt +dot -Tsvg debug_container.dot > debug_container.svg +``` + +Many other tools including some IDEs support working with DOT files. diff --git a/versioned_docs/version-0.47/integrate/libraries/02-collections.md b/versioned_docs/version-0.47/integrate/libraries/02-collections.md new file mode 100644 index 000000000..fc74594ec --- /dev/null +++ b/versioned_docs/version-0.47/integrate/libraries/02-collections.md @@ -0,0 +1,1119 @@ +# Collections + +Collections is a library meant to simplify the experience with respect to module state handling. + +Cosmos SDK modules handle their state using the `KVStore` interface. The problem with working with +`KVStore` is that it forces you to think of state as a bytes KV pairings when in reality the majority of +state comes from complex concrete golang objects (strings, ints, structs, etc.). + +Collections allows you to work with state as if they were normal golang objects and removes the need +for you to think of your state as raw bytes in your code. + +It also allows you to migrate your existing state without causing any state breakage that forces you into +tedious and complex chain state migrations. + +## Installation + +To install collections in your cosmos-sdk chain project, run the following command: + +```shell +go get cosmossdk.io/collections +``` + +## Core types + +Collections offers 5 different APIs to work with state, which will be explored in the next sections, these APIs are: +- ``Map``: to work with typed arbitrary KV pairings. +- ``KeySet``: to work with just typed keys +- ``Item``: to work with just one typed value +- ``Sequence``: which is a monotonically increasing number. +- ``IndexedMap``: which combines ``Map`` and `KeySet` to provide a `Map` with indexing capabilities. + +## Preliminary components + +Before exploring the different collections types and their capability it is necessary to introduce +the three components that every collection shares. In fact when instantiating a collection type by doing, for example, +```collections.NewMap/collections.NewItem/...``` you will find yourself having to pass them some common arguments. + +For example, in code: + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var AllowListPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + AllowList collections.KeySet[string] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + + return Keeper{ + AllowList: collections.NewKeySet(sb, AllowListPrefix, "allow_list", collections.StringKey), + } +} + +``` + +Let's analyse the shared arguments, what they do, and why we need them. + +### SchemaBuilder + +The first argument passed is the ``SchemaBuilder`` + +`SchemaBuilder` is a structure that keeps track of all the state of a module, it is not required by the collections + to deal with state but it offers a dynamic and reflective way for clients to explore a module's state. + +We instantiate a ``SchemaBuilder`` by passing it a function that given the modules store key returns the module's specific store. + +We then need to pass the schema builder to every collection type we instantiate in our keeper, in our case the `AllowList`. + +### Prefix + +The second argument passed to our ``KeySet`` is a `collections.Prefix`, a prefix represents a partition of the module's `KVStore` +where all the state of a specific collection will be saved. + +Since a module can have multiple collections, the following is expected: +- module params will become a `collections.Item` +- the `AllowList` is a `collections.KeySet` + +We don't want a collection to write over the state of the other collection so we pass it a prefix, which defines a storage +partition owned by the collection. + +If you already built modules, the prefix translates to the items you were creating in your ``types/keys.go`` file, example: https://github.com/cosmos/cosmos-sdk/blob/main/x/feegrant/key.go#L27 + +your old: +```go +var ( + // FeeAllowanceKeyPrefix is the set of the kvstore for fee allowance data + // - 0x00: allowance + FeeAllowanceKeyPrefix = []byte{0x00} + + // FeeAllowanceQueueKeyPrefix is the set of the kvstore for fee allowance keys data + // - 0x01: + FeeAllowanceQueueKeyPrefix = []byte{0x01} +) +``` +becomes: +```go +var ( + // FeeAllowanceKeyPrefix is the set of the kvstore for fee allowance data + // - 0x00: allowance + FeeAllowanceKeyPrefix = collections.NewPrefix(0) + + // FeeAllowanceQueueKeyPrefix is the set of the kvstore for fee allowance keys data + // - 0x01: + FeeAllowanceQueueKeyPrefix = collections.NewPrefix(1) +) +``` + +#### Rules + +``collections.NewPrefix`` accepts either `uint8`, `string` or `[]bytes` it's good practice to use an always increasing `uint8`for disk space efficiency. + +A collection **MUST NOT** share the same prefix as another collection in the same module, and a collection prefix **MUST NEVER** start with the same prefix as another, examples: + +```go +prefix1 := collections.NewPrefix("prefix") +prefix2 := collections.NewPrefix("prefix") // THIS IS BAD! +``` + +```go +prefix1 := collections.NewPrefix("a") +prefix2 := collections.NewPrefix("aa") // prefix2 starts with the same as prefix1: BAD!!! +``` +### Human-Readable Name + +The third parameter we pass to a collection is a string, which is a human-readable name. +It is needed to make the role of a collection understandable by clients who have no clue about +what a module is storing in state. + +#### Rules + +Each collection in a module **MUST** have a unique humanised name. + +## Key and Value Codecs + +A collection is generic over the type you can use as keys or values. +This makes collections dumb, but also means that hypothetically we can store everything +that can be a go type into a collection. We are not bounded to any type of encoding (be it proto, json or whatever) + +So a collection needs to be given a way to understand how to convert your keys and values to bytes. +This is achieved through ``KeyCodec`` and `ValueCodec`, which are arguments that you pass to your +collections when you're instantiating them using the ```collections.NewMap/collections.NewItem/...``` +instantiation functions. + +NOTE: Generally speaking you will never be required to implement your own ``Key/ValueCodec`` as +the SDK and collections libraries already come with default, safe and fast implementation of those. +You might need to implement them only if you're migrating to collections and there are state layout incompatibilities. + +Let's explore an example: + +````go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var IDsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + IDs collections.Map[string, uint64] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + + return Keeper{ + IDs: collections.NewMap(sb, IDsPrefix, "ids", collections.StringKey, collections.Uint64Value), + } +} +```` + +We're now instantiating a map where the key is string and the value is `uint64`. +We already know the first three arguments of the ``NewMap`` function. + +The fourth parameter is our `KeyCodec`, we know that the ``Map`` has `string` as key so we pass it a `KeyCodec` that handles strings as keys. + +The fifth parameter is our `ValueCodec`, we know that the `Map` as a `uint64` as value so we pass it a `ValueCodec` that handles uint64. + +Collections already comes with all the required implementations for golang primitive types. + +Let's make another example, this falls closer to what we build using cosmos SDK, let's say we want +to create a `collections.Map` that maps account addresses to their base account. So we want to map an `sdk.AccAddress` to an `auth.BaseAccount` (which is a proto): + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts collections.Map[sdk.AccAddress, authtypes.BaseAccount] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewMap(sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollValue[authtypes.BaseAccount](cdc)), + } +} +``` + +As we can see here since our `collections.Map` maps `sdk.AccAddress` to `authtypes.BaseAccount`, +we use the `sdk.AccAddressKey` which is the `KeyCodec` implementation for `AccAddress` and we use `codec.CollValue` to +encode our proto type `BaseAccount`. + +Generally speaking you will always find the respective key and value codecs for types in the `go.mod` path you're using +to import that type. If you want to encode proto values refer to the codec `codec.CollValue` function, which allows you +to encode any type implement the `proto.Message` interface. + +## Map + +We analyse the first and most important collection type, the ``collections.Map``. +This is the type that everything else builds on top of. + +### Use case + +A `collections.Map` is used to map arbitrary keys with arbitrary values. + +### Example + +It's easier to explain a `collections.Map` capabilities through an example: + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "fmt" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts collections.Map[sdk.AccAddress, authtypes.BaseAccount] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewMap(sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollValue[authtypes.BaseAccount](cdc)), + } +} + +func (k Keeper) CreateAccount(ctx sdk.Context, addr sdk.AccAddress, account authtypes.BaseAccount) error { + has, err := k.Accounts.Has(ctx, addr) + if err != nil { + return err + } + if has { + return fmt.Errorf("account already exists: %s", addr) + } + + err = k.Accounts.Set(ctx, addr, account) + if err != nil { + return err + } + return nil +} + +func (k Keeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) (authtypes.BaseAccount, error) { + acc, err := k.Accounts.Get(ctx, addr) + if err != nil { + return authtypes.BaseAccount{}, err + } + + return acc, nil +} + +func (k Keeper) RemoveAccount(ctx sdk.Context, addr sdk.AccAddress) error { + err := k.Accounts.Remove(ctx, addr) + if err != nil { + return err + } + return nil +} +``` + +#### Set method + +Set maps with the provided `AccAddress` (the key) to the `auth.BaseAccount` (the value). + +Under the hood the `collections.Map` will convert the key and value to bytes using the [key and value codec](README.md#key-and-value-codecs). +It will prepend to our bytes key the [prefix](README.md#prefix) and store it in the KVStore of the module. + +#### Has method + +The has method reports if the provided key exists in the store. + +#### Get method + +The get method accepts the `AccAddress` and returns the associated `auth.BaseAccount` if it exists, otherwise it errors. + +#### Remove method + +The remove method accepts the `AccAddress` and removes it from the store. It won't report errors +if it does not exist, to check for existence before removal use the ``Has`` method. + +#### Iteration + +Iteration has a separate section. + +## KeySet + +The second type of collection is `collections.KeySet`, as the word suggests it maintains +only a set of keys without values. + +#### Implementation curiosity + +A `collections.KeySet` is just a `collections.Map` with a `key` but no value. +The value internally is always the same and is represented as an empty byte slice ```[]byte{}```. + +### Example + +As always we explore the collection type through an example: + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ValidatorsSetPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + ValidatorsSet collections.KeySet[sdk.ValAddress] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + ValidatorsSet: collections.NewKeySet(sb, ValidatorsSetPrefix, "validators_set", sdk.ValAddressKey), + } +} + +func (k Keeper) AddValidator(ctx sdk.Context, validator sdk.ValAddress) error { + has, err := k.ValidatorsSet.Has(ctx, validator) + if err != nil { + return err + } + if has { + return fmt.Errorf("validator already in set: %s", validator) + } + + err = k.ValidatorsSet.Set(ctx, validator) + if err != nil { + return err + } + + return nil +} + +func (k Keeper) RemoveValidator(ctx sdk.Context, validator sdk.ValAddress) error { + err := k.ValidatorsSet.Remove(ctx, validator) + if err != nil { + return err + } + return nil +} +``` +The first difference we notice is that `KeySet` needs use to specify only one type parameter: the key (`sdk.ValAddress` in this case). +The second difference we notice is that `KeySet` in its `NewKeySet` function does not require +us to specify a `ValueCodec` but only a `KeyCodec`. This is because a `KeySet` only saves keys and not values. + +Let's explore the methods. + +#### Has method + +Has allows us to understand if a key is present in the `collections.KeySet` or not, functions in the same way as `collections.Map.Has +` + +#### Set method + +Set inserts the provided key in the `KeySet`. + +#### Remove method + +Remove removes the provided key from the `KeySet`, it does not error if the key does not exist, +if existence check before removal is required it needs to be coupled with the `Has` method. + +## Item + +The third type of collection is the `collections.Item`. +It stores only one single item, it's useful for example for parameters, there's only one instance +of parameters in state always. + +#### implementation curiosity + +A `collections.Item` is just a `collections.Map` with no key but just a value. +The key is the prefix of the collection! + +### Example + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +var ParamsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Params collections.Item[stakingtypes.Params] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Params: collections.NewItem(sb, ParamsPrefix, "params", codec.CollValue[stakingtypes.Params](cdc)), + } +} + +func (k Keeper) UpdateParams(ctx sdk.Context, params stakingtypes.Params) error { + err := k.Params.Set(ctx, params) + if err != nil { + return err + } + return nil +} + +func (k Keeper) GetParams(ctx sdk.Context) (stakingtypes.Params, error) { + return k.Params.Get(ctx) +} +``` + +The first key difference we notice is that we specify only one type parameter, which is the value we're storing. +The second key difference is that we don't specify the `KeyCodec`, since we store only one item we already know the key +and the fact that it is constant. + +## Iteration + +One of the key features of the ``KVStore`` is iterating over keys. + +Collections which deal with keys (so `Map`, `KeySet` and `IndexedMap`) allow you to iterate +over keys in a safe and typed way. They all share the same API, the only difference being +that ``KeySet`` returns a different type of `Iterator` because `KeySet` only deals with keys. + +:::note + +Every collection shares the same `Iterator` semantics. + +::: + +Let's have a look at the `Map.Iterate` method: + +```go +func (m Map[K, V]) Iterate(ctx context.Context, ranger Ranger[K]) (Iterator[K, V], error) +``` + +It accepts a `collections.Ranger[K]`, which is an API that instructs map on how to iterate over keys. +As always we don't need to implement anything here as `collections` already provides some generic `Ranger` implementers +that expose all you need to work with ranges. + +### Example + +We have a `collections.Map` that maps accounts using `uint64` IDs. + +```go +package collections + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts collections.Map[uint64, authtypes.BaseAccount] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewMap(sb, AccountsPrefix, "accounts", collections.Uint64Key, codec.CollValue[authtypes.BaseAccount](cdc)), + } +} + +func (k Keeper) GetAllAccounts(ctx sdk.Context) ([]authtypes.BaseAccount, error) { + // passing a nil Ranger equals to: iterate over every possible key + iter, err := k.Accounts.Iterate(ctx, nil) + if err != nil { + return nil, err + } + accounts, err := iter.Values() + if err != nil { + return nil, err + } + + return accounts, err +} + +func (k Keeper) IterateAccountsBetween(ctx sdk.Context, start, end uint64) ([]authtypes.BaseAccount, error) { + // The collections.Range API offers a lot of capability + // like defining where the iteration starts or ends. + rng := new(collections.Range[uint64]). + StartInclusive(start). + EndExclusive(end). + Descending() + + iter, err := k.Accounts.Iterate(ctx, rng) + if err != nil { + return nil, err + } + accounts, err := iter.Values() + if err != nil { + return nil, err + } + + return accounts, nil +} + +func (k Keeper) IterateAccounts(ctx sdk.Context, do func(id uint64, acc authtypes.BaseAccount) (stop bool)) error { + iter, err := k.Accounts.Iterate(ctx, nil) + if err != nil { + return err + } + defer iter.Close() + + for ; iter.Valid(); iter.Next() { + kv, err := iter.KeyValue() + if err != nil { + return err + } + + if do(kv.Key, kv.Value) { + break + } + } + return nil +} +``` + +Let's analyse each method in the example and how it makes use of the `Iterate` and the returned `Iterator` API. + +#### GetAllAccounts + +In `GetAllAccounts` we pass to our `Iterate` a nil `Ranger`. This means that the returned `Iterator` will include +all the existing keys within the collection. + +Then we use some the `Values` method from the returned `Iterator` API to collect all the values into a slice. + +`Iterator` offers other methods such as `Keys()` to collect only the keys and not the values and `KeyValues` to collect +all the keys and values. + + +#### IterateAccountsBetween + +Here we make use of the `collections.Range` helper to specialise our range. +We make it start in a point through `StartInclusive` and end in the other with `EndExclusive`, then +we instruct it to report us results in reverse order through `Descending` + +Then we pass the range instruction to `Iterate` and get an `Iterator`, which will contain only the results +we specified in the range. + +Then we use again th `Values` method of the `Iterator` to collect all the results. + +`collections.Range` also offers a `Prefix` API which is not appliable to all keys types, +for example uint64 cannot be prefix because it is of constant size, but a `string` key +can be prefixed. + +#### IterateAccounts + +Here we showcase how to lazily collect values from an Iterator. + +:::note + +`Keys/Values/KeyValues` fully consume and close the `Iterator`, here we need to explicitly do a `defer iterator.Close()` call. + +::: + +`Iterator` also exposes a `Value` and `Key` method to collect only the current value or key, if collecting both is not needed. + +:::note + +For this `callback` pattern, collections expose a `Walk` API. + +::: + +## Composite keys + +So far we've worked only with simple keys, like `uint64`, the account address, etc. +There are some more complex cases in, which we need to deal with composite keys. + +A key is composite when it is composed of multiple keys, for example bank balances as stored as the composite key +`(AccAddress, string)` where the first part is the address holding the coins and the second part is the denom. + +Example, let's say address `BOB` holds `10atom,15osmo`, this is how it is stored in state: + +``` +(bob, atom) => 10 +(bob, osmos) => 15 +``` + +Now this allows to efficiently get a specific denom balance of an address, by simply `getting` `(address, denom)`, or getting all the balances +of an address by prefixing over `(address)`. + +Let's see now how we can work with composite keys using collections. + +### Example + +In our example we will show-case how we can use collections when we are dealing with balances, similar to bank, +a balance is a mapping between `(address, denom) => math.Int` the composite key in our case is `(address, denom)`. + +## Instantiation of a composite key collection + +```go +package collections + +import ( + "cosmossdk.io/collections" + "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + + +var BalancesPrefix = collections.NewPrefix(1) + +type Keeper struct { + Schema collections.Schema + Balances collections.Map[collections.Pair[sdk.AccAddress, string], math.Int] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Balances: collections.NewMap( + sb, BalancesPrefix, "balances", + collections.PairKeyCodec(sdk.AccAddressKey, collections.StringKey), + math.IntValue, + ), + } +} +``` + +#### The Map Key definition + +First of all we can see that in order to define a composite key of two elements we use the `collections.Pair` type: +````go +collections.Map[collections.Pair[sdk.AccAddress, string], math.Int] +```` + +`collections.Pair` defines a key composed of two other keys, in our case the first part is `sdk.AccAddress`, the second +part is `string`. + +#### The Key Codec instantiation + +The arguments to instantiate are always the same, the only thing that changes is how we instantiate +the ``KeyCodec``, since this key is composed of two keys we use `collections.PairKeyCodec`, which generates +a `KeyCodec` composed of two key codecs. The first one will encode the first part of the key, the second one will +encode the second part of the key. + + +### Working with composite key collections + +Let's expand on the example we used before: + +````go +var BalancesPrefix = collections.NewPrefix(1) + +type Keeper struct { + Schema collections.Schema + Balances collections.Map[collections.Pair[sdk.AccAddress, string], math.Int] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Balances: collections.NewMap( + sb, BalancesPrefix, "balances", + collections.PairKeyCodec(sdk.AccAddressKey, collections.StringKey), + math.IntValue, + ), + } +} + +func (k Keeper) SetBalance(ctx sdk.Context, address sdk.AccAddress, denom string, amount math.Int) error { + key := collections.Join(address, denom) + return k.Balances.Set(ctx, key, amount) +} + +func (k Keeper) GetBalance(ctx sdk.Context, address sdk.AccAddress, denom string) (math.Int, error) { + return k.Balances.Get(ctx, collections.Join(address, denom)) +} + +func (k Keeper) GetAllAddressBalances(ctx sdk.Context, address sdk.AccAddress) (sdk.Coins, error) { + balances := sdk.NewCoins() + + rng := collections.NewPrefixedPairRange[sdk.AccAddress, string](address) + + iter, err := k.Balances.Iterate(ctx, rng) + if err != nil { + return nil, err + } + + kvs, err := iter.KeyValues() + if err != nil { + return nil, err + } + + for _, kv := range kvs { + balances = balances.Add(sdk.NewCoin(kv.Key.K2(), kv.Value)) + } + return balances, nil +} + +func (k Keeper) GetAllAddressBalancesBetween(ctx sdk.Context, address sdk.AccAddress, startDenom, endDenom string) (sdk.Coins, error) { + rng := collections.NewPrefixedPairRange[sdk.AccAddress, string](address). + StartInclusive(startDenom). + EndInclusive(endDenom) + + iter, err := k.Balances.Iterate(ctx, rng) + if err != nil { + return nil, err + } + ... +} +```` + +#### SetBalance + +As we can see here we're setting the balance of an address for a specific denom. +We use the `collections.Join` function to generate the composite key. +`collections.Join` returns a `collections.Pair` (which is the key of our `collections.Map`) + +`collections.Pair` contains the two keys we have joined, it also exposes two methods: `K1` to fetch the 1st part of the +key and `K2` to fetch the second part. + +As always, we use the `collections.Map.Set` method to map the composite key to our value (`math.Int`in this case) + +#### GetBalance + +To get a value in composite key collection, we simply use `collections.Join` to compose the key. + +#### GetAllAddressBalances + +We use `collections.PrefixedPairRange` to iterate over all the keys starting with the provided address. +Concretely the iteration will report all the balances belonging to the provided address. + +The first part is that we instantiate a `PrefixedPairRange`, which is a `Ranger` implementer aimed to help +in `Pair` keys iterations. + +```go + rng := collections.NewPrefixedPairRange[sdk.AccAddress, string](address) +``` + +As we can see here we're passing the type parameters of the `collections.Pair` because golang type inference +with respect to generics is not as permissive as other languages, so we need to explitly say what are the types of the pair key. + +#### GetAllAddressesBalancesBetween + +This showcases how we can further specialise our range to limit the results further, by specifying +the range between the second part of the key (in our case the denoms, which are strings). + +## IndexedMap + +`collections.IndexedMap` is a collection that uses under the hood a `collections.Map`, and has a struct, which contains the indexes that we need to define. + +### Example + +Let's say we have an `auth.BaseAccount` struct which looks like the following: + +```go +type BaseAccount struct { + AccountNumber uint64 `protobuf:"varint,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"` + Sequence uint64 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"` +} +``` + +First of all, when we save our accounts in state we map them using a primary key `sdk.AccAddress`. +If it were to be a `collections.Map` it would be `collections.Map[sdk.AccAddres, authtypes.BaseAccount]`. + +Then we also want to be able to get an account not only by its `sdk.AccAddress`, but also by its `AccountNumber`. + +So we can say we want to create an `Index` that maps our `BaseAccount` to its `AccountNumber`. + +We also know that this `Index` is unique. Unique means that there can only be one `BaseAccount` that maps to a specific +`AccountNumber`. + +First of all, we start by defining the object that contains our index: + +```go +var AccountsNumberIndexPrefix = collections.NewPrefix(1) + +type AccountsIndexes struct { + Number *indexes.Unique[uint64, sdk.AccAddress, authtypes.BaseAccount] +} + +func (a AccountsIndexes) IndexesList() []collections.Index[sdk.AccAddress, authtypes.BaseAccount] { + return []collections.Index[sdk.AccAddress, authtypes.BaseAccount]{a.Number} +} + +func NewAccountIndexes(sb *collections.SchemaBuilder) AccountsIndexes { + return AccountsIndexes{ + Number: indexes.NewUnique( + sb, AccountsNumberIndexPrefix, "accounts_by_number", + collections.Uint64Key, sdk.AccAddressKey, + func(_ sdk.AccAddress, v authtypes.BaseAccount) (uint64, error) { + return v.AccountNumber, nil + }, + ), + } +} +``` + +We create an `AccountIndexes` struct which contains a field: `Number`. This field represents our `AccountNumber` index. +`AccountNumber` is a field of `authtypes.BaseAccount` and it's a `uint64`. + +Then we can see in our `AccountIndexes` struct the `Number` field is defined as: + +```go +*indexes.Unique[uint64, sdk.AccAddress, authtypes.BaseAccount] +``` + +Where the first type parameter is `uint64`, which is the field type of our index. +The second type parameter is the primary key `sdk.AccAddress` +And the third type parameter is the actual object we're storing `authtypes.BaseAccount`. + +Then we implement a function called `IndexesList` on our `AccountIndexes` struct, this will be used +by the `IndexedMap` to keep the underlying map in sync with the indexes, in our case `Number`. +This function just needs to return the slice of indexes contained in the struct. + +Then we create a `NewAccountIndexes` function that instantiates and returns the `AccountsIndexes` struct. + +The function takes a `SchemaBuilder`. Then we instantiate our `indexes.Unique`, let's analyse the arguments we pass to +`indexes.NewUnique`. + +#### Instantiating a `indexes.Unique` + +The first three arguments, we already know them, they are: `SchemaBuilder`, `Prefix` which is our index prefix (the partition +where index keys relationship for the `Number` index will be maintained), and the human name for the `Number` index. + +The second argument is a `collections.Uint64Key` which is a key codec to deal with `uint64` keys, we pass that because +the key we're trying to index is a `uint64` key (the account number), and then we pass as fifth argument the primary key codec, +which in our case is `sdk.AccAddress` (remember: we're mapping `sdk.AccAddress` => `BaseAccount`). + +Then as last parameter we pass a function that: given the `BaseAccount` returns its `AccountNumber`. + +After this we can proceed instantiating our `IndexedMap`. + +```go +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts *collections.IndexedMap[sdk.AccAddress, authtypes.BaseAccount, AccountsIndexes] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewIndexedMap( + sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollValue[authtypes.BaseAccount](cdc), + NewAccountIndexes(sb), + ), + } +} +``` + +As we can see here what we do, for now, is the same thing as we did for `collections.Map`. +We pass it the `SchemaBuilder`, the `Prefix` where we plan to store the mapping between `sdk.AccAddress` and `authtypes.BaseAccount`, +the human name and the respective `sdk.AccAddress` key codec and `authtypes.BaseAccount` value codec. + +Then we pass the instantiation of our `AccountIndexes` through `NewAccountIndexes`. + +Full example: + +```go +package docs + +import ( + "cosmossdk.io/collections" + "cosmossdk.io/collections/indexes" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsNumberIndexPrefix = collections.NewPrefix(1) + +type AccountsIndexes struct { + Number *indexes.Unique[uint64, sdk.AccAddress, authtypes.BaseAccount] +} + +func (a AccountsIndexes) IndexesList() []collections.Index[sdk.AccAddress, authtypes.BaseAccount] { + return []collections.Index[sdk.AccAddress, authtypes.BaseAccount]{a.Number} +} + +func NewAccountIndexes(sb *collections.SchemaBuilder) AccountsIndexes { + return AccountsIndexes{ + Number: indexes.NewUnique( + sb, AccountsNumberIndexPrefix, "accounts_by_number", + collections.Uint64Key, sdk.AccAddressKey, + func(_ sdk.AccAddress, v authtypes.BaseAccount) (uint64, error) { + return v.AccountNumber, nil + }, + ), + } +} + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts *collections.IndexedMap[sdk.AccAddress, authtypes.BaseAccount, AccountsIndexes] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewIndexedMap( + sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollValue[authtypes.BaseAccount](cdc), + NewAccountIndexes(sb), + ), + } +} +``` + +### Working with IndexedMaps + +Whilst instantiating `collections.IndexedMap` is tedious, working with them is extremely smooth. + +Let's take the full example, and expand it with some use-cases. + +```go +package docs + +import ( + "cosmossdk.io/collections" + "cosmossdk.io/collections/indexes" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsNumberIndexPrefix = collections.NewPrefix(1) + +type AccountsIndexes struct { + Number *indexes.Unique[uint64, sdk.AccAddress, authtypes.BaseAccount] +} + +func (a AccountsIndexes) IndexesList() []collections.Index[sdk.AccAddress, authtypes.BaseAccount] { + return []collections.Index[sdk.AccAddress, authtypes.BaseAccount]{a.Number} +} + +func NewAccountIndexes(sb *collections.SchemaBuilder) AccountsIndexes { + return AccountsIndexes{ + Number: indexes.NewUnique( + sb, AccountsNumberIndexPrefix, "accounts_by_number", + collections.Uint64Key, sdk.AccAddressKey, + func(_ sdk.AccAddress, v authtypes.BaseAccount) (uint64, error) { + return v.AccountNumber, nil + }, + ), + } +} + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts *collections.IndexedMap[sdk.AccAddress, authtypes.BaseAccount, AccountsIndexes] +} + +func NewKeeper(storeKey *storetypes.KVStoreKey, cdc codec.BinaryCodec) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewIndexedMap( + sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollValue[authtypes.BaseAccount](cdc), + NewAccountIndexes(sb), + ), + } +} + +func (k Keeper) CreateAccount(ctx sdk.Context, addr sdk.AccAddress) error { + nextAccountNumber := k.getNextAccountNumber() + + newAcc := authtypes.BaseAccount{ + AccountNumber: nextAccountNumber, + Sequence: 0, + } + + return k.Accounts.Set(ctx, addr, newAcc) +} + +func (k Keeper) RemoveAccount(ctx sdk.Context, addr sdk.AccAddress) error { + return k.Accounts.Remove(ctx, addr) +} + +func (k Keeper) GetAccountByNumber(ctx sdk.Context, accNumber uint64) (sdk.AccAddress, authtypes.BaseAccount, error) { + accAddress, err := k.Accounts.Indexes.Number.MatchExact(ctx, accNumber) + if err != nil { + return nil, authtypes.BaseAccount{}, err + } + + acc, err := k.Accounts.Get(ctx, accAddress) + return accAddress, acc, nil +} + +func (k Keeper) GetAccountsByNumber(ctx sdk.Context, startAccNum, endAccNum uint64) ([]authtypes.BaseAccount, error) { + rng := new(collections.Range[uint64]). + StartInclusive(startAccNum). + EndInclusive(endAccNum) + + iter, err := k.Accounts.Indexes.Number.Iterate(ctx, rng) + if err != nil { + return nil, err + } + + return indexes.CollectValues(ctx, k.Accounts, iter) +} + + +func (k Keeper) getNextAccountNumber() uint64 { + return 0 +} +``` + +## Collections with interfaces as values + +Although cosmos-sdk is shifting away from the usage of interface registry, there are still some places where it is used. +In order to support old code, we have to support collections with interface values. + +The generic `codec.CollValue` is not able to handle interface values, so we need to use a special type `codec.CollValueInterface`. +`codec.CollValueInterface` takes a `codec.BinaryCodec` as an argument, and uses it to marshal and unmarshal values as interfaces. +The `codec.CollValueInterface` lives in the `codec` package, whose import path is `github.com/cosmos/cosmos-sdk/codec`. + +### Instantiating Collections with interface values + +In order to instantiate a collection with interface values, we need to use `codec.CollValueInterface` instead of `codec.CollValue`. + +```go +package example + +import ( + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var AccountsPrefix = collections.NewPrefix(0) + +type Keeper struct { + Schema collections.Schema + Accounts *collections.Map[sdk.AccAddress, sdk.AccountI] +} + +func NewKeeper(cdc codec.BinaryCodec, storeKey *storetypes.KVStoreKey) Keeper { + sb := collections.NewSchemaBuilder(sdk.OpenKVStore(storeKey)) + return Keeper{ + Accounts: collections.NewMap( + sb, AccountsPrefix, "accounts", + sdk.AccAddressKey, codec.CollInterfaceValue[sdk.AccountI](cdc), + ), + } +} + +func (k Keeper) SaveBaseAccount(ctx sdk.Context, account authtypes.BaseAccount) error { + return k.Accounts.Set(ctx, account.GetAddress(), account) +} + +func (k Keeper) SaveModuleAccount(ctx sdk.Context, account authtypes.ModuleAccount) error { + return k.Accounts.Set(ctx, account.GetAddress(), account) +} + +func (k Keeper) GetAccount(ctx sdk.context, addr sdk.AccAddress) (sdk.AccountI, error) { + return k.Accounts.Get(ctx, addr) +} +``` diff --git a/versioned_docs/version-0.47/integrate/libraries/03-orm.md b/versioned_docs/version-0.47/integrate/libraries/03-orm.md new file mode 100644 index 000000000..14bc84b88 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/libraries/03-orm.md @@ -0,0 +1,329 @@ +# ORM + +The Cosmos SDK ORM is a state management library that provides a rich, but opinionated set of tools for managing a +module's state. It provides support for: + +* type safe management of state +* multipart keys +* secondary indexes +* unique indexes +* easy prefix and range queries +* automatic genesis import/export +* automatic query services for clients, including support for light client proofs (still in development) +* indexing state data in external databases (still in development) + +## Design and Philosophy + +The ORM's data model is inspired by the relational data model found in SQL databases. The core abstraction is a table +with a primary key and optional secondary indexes. + +Because the Cosmos SDK uses protobuf as its encoding layer, ORM tables are defined directly in .proto files using +protobuf options. Each table is defined by a single protobuf `message` type and a schema of multiple tables is +represented by a single .proto file. + +Table structure is specified in the same file where messages are defined in order to make it easy to focus on better +design of the state layer. Because blockchain state layout is part of the public API for clients (TODO: link to docs on +light client proofs), it is important to think about the state layout as being part of the public API of a module. +Changing the state layout actually breaks clients, so it is ideal to think through it carefully up front and to aim for +a design that will eliminate or minimize breaking changes down the road. Also, good design of state enables building +more performant and sophisticated applications. Providing users with a set of tools inspired by relational databases +which have a long history of database design best practices and allowing schema to be specified declaratively in a +single place are design choices the ORM makes to enable better design and more durable APIs. + +Also, by only supporting the table abstraction as opposed to key-value pair maps, it is easy to add to new +columns/fields to any data structure without causing a breaking change and the data structures can easily be indexed in +any off-the-shelf SQL database for more sophisticated queries. + +The encoding of fields in keys is designed to support ordered iteration for all protobuf primitive field types +except for `bytes` as well as the well-known types `google.protobuf.Timestamp` and `google.protobuf.Duration`. Encodings +are optimized for storage space when it makes sense (see the documentation in `cosmos/orm/v1/orm.proto` for more details) +and table rows do not use extra storage space to store key fields in the value. + +We recommend that users of the ORM attempt to follow database design best practices such as +[normalization](https://en.wikipedia.org/wiki/Database_normalization) (at least 1NF). +For instance, defining `repeated` fields in a table is considered an anti-pattern because breaks first normal form (1NF). +Although we support `repeated` fields in tables, they cannot be used as key fields for this reason. This may seem +restrictive but years of best practice (and also experience in the SDK) have shown that following this pattern +leads to easier to maintain schemas. + +To illustrate the motivation for these principles with an example from the SDK, historically balances were stored +as a mapping from account -> map of denom to amount. This did not scale well because an account with 100 token balances +needed to be encoded/decoded every time a single coin balance changed. Now balances are stored as account,denom -> amount +as in the example above. With the ORM's data model, if we wanted to add a new field to `Balance` such as +`unlocked_balance` (if vesting accounts were redesigned in this way), it would be easy to add it to this table without +requiring a data migration. Because of the ORM's optimizations, the account and denom are only stored in the key part +of storage and not in the value leading to both a flexible data model and efficient usage of storage. + +## Defining Tables + +To define a table: + +1) create a .proto file to describe the module's state (naming it `state.proto` is recommended for consistency), +and import "cosmos/orm/v1/orm.proto", ex: + +```protobuf +syntax = "proto3"; +package bank_example; + +import "cosmos/orm/v1/orm.proto"; +``` + +2) define a `message` for the table, ex: + +```protobuf +message Balance { + bytes account = 1; + string denom = 2; + uint64 balance = 3; +} +``` + +3) add the `cosmos.orm.v1.table` option to the table and give the table an `id` unique within this .proto file: + +```protobuf +message Balance { + option (cosmos.orm.v1.table) = { + id: 1 + }; + + bytes account = 1; + string denom = 2; + uint64 balance = 3; +} +``` + +4) define the primary key field or fields, as a comma-separated list of the fields from the message which should make +up the primary key: + +```protobuf +message Balance { + option (cosmos.orm.v1.table) = { + id: 1 + primary_key: { fields: "account,denom" } + }; + + bytes account = 1; + string denom = 2; + uint64 balance = 3; +} +``` + +5) add any desired secondary indexes by specifying an `id` unique within the table and a comma-separate list of the +index fields: + +```protobuf +message Balance { + option (cosmos.orm.v1.table) = { + id: 1; + primary_key: { fields: "account,denom" } + index: { id: 1 fields: "denom" } // this allows querying for the accounts which own a denom + }; + + bytes account = 1; + string denom = 2; + uint64 amount = 3; +} +``` + +### Auto-incrementing Primary Keys + +A common pattern in SDK modules and in database design is to define tables with a single integer `id` field with an +automatically generated primary key. In the ORM we can do this by setting the `auto_increment` option to `true` on the +primary key, ex: + +```protobuf +message Account { + option (cosmos.orm.v1.table) = { + id: 2; + primary_key: { fields: "id", auto_increment: true } + }; + + uint64 id = 1; + bytes address = 2; +} +``` + +### Unique Indexes + +A unique index can be added by setting the `unique` option to `true` on an index, ex: + +```protobuf +message Account { + option (cosmos.orm.v1.table) = { + id: 2; + primary_key: { fields: "id", auto_increment: true } + index: {id: 1, fields: "address", unique: true} + }; + + uint64 id = 1; + bytes address = 2; +} +``` + +### Singletons + +The ORM also supports a special type of table with only one row called a `singleton`. This can be used for storing +module parameters. Singletons only need to define a unique `id` and that cannot conflict with the id of other +tables or singletons in the same .proto file. Ex: + +```protobuf +message Params { + option (cosmos.orm.v1.singleton) = { + id: 3; + }; + + google.protobuf.Duration voting_period = 1; + uint64 min_threshold = 2; +} +``` + +## Running Codegen + +NOTE: the ORM will only work with protobuf code that implements the [google.golang.org/protobuf](https://pkg.go.dev/google.golang.org/protobuf) +API. That means it will not work with code generated using gogo-proto. + +To install the ORM's code generator, run: + +```shell +go install cosmossdk.io/orm/cmd/protoc-gen-go-cosmos-orm@latest +``` + +The recommended way to run the code generator is to use [buf build](https://docs.buf.build/build/usage). +This is an example `buf.gen.yaml` that runs `protoc-gen-go`, `protoc-gen-go-grpc` and `protoc-gen-go-cosmos-orm` +using buf managed mode: + +```yaml +version: v1 +managed: + enabled: true + go_package_prefix: + default: foo.bar/api # the go package prefix of your package + override: + buf.build/cosmos/cosmos-sdk: cosmossdk.io/api # required to import the Cosmos SDK api module +plugins: + - name: go + out: . + opt: paths=source_relative + - name: go-grpc + out: . + opt: paths=source_relative + - name: go-cosmos-orm + out: . + opt: paths=source_relative +``` + +## Using the ORM in a module + +### Initialization + +To use the ORM in a module, first create a `ModuleSchemaDescriptor`. This tells the ORM which .proto files have defined +an ORM schema and assigns them all a unique non-zero id. Ex: + +```go +var MyModuleSchema = &ormv1alpha1.ModuleSchemaDescriptor{ + SchemaFile: []*ormv1alpha1.ModuleSchemaDescriptor_FileEntry{ + { + Id: 1, + ProtoFileName: mymodule.File_my_module_state_proto.Path(), + }, + }, +} +``` + +In the ORM generated code for a file named `state.proto`, there should be an interface `StateStore` that got generated +with a constructor `NewStateStore` that takes a parameter of type `ormdb.ModuleDB`. Add a reference to `StateStore` +to your module's keeper struct. Ex: + +```go +type Keeper struct { + db StateStore +} +``` + +Then instantiate the `StateStore` instance via an `ormdb.ModuleDB` that is instantiated from the `SchemaDescriptor` +above and one or more store services from `cosmossdk.io/core/store`. Ex: + +```go +func NewKeeper(storeService store.KVStoreService) (*Keeper, error) { + modDb, err := ormdb.NewModuleDB(MyModuleSchema, ormdb.ModuleDBOptions{KVStoreService: storeService}) + if err != nil { + return nil, err + } + db, err := NewStateStore(modDb) + if err != nil { + return nil, err + } + return Keeper{db: db}, nil +} +``` + +### Using the generated code + +The generated code for the ORM contains methods for inserting, updating, deleting and querying table entries. +For each table in a .proto file, there is a type-safe table interface implemented in generated code. For instance, +for a table named `Balance` there should be a `BalanceTable` interface that looks like this: + +```go +type BalanceTable interface { + Insert(ctx context.Context, balance *Balance) error + Update(ctx context.Context, balance *Balance) error + Save(ctx context.Context, balance *Balance) error + Delete(ctx context.Context, balance *Balance) error + Has(ctx context.Context, acocunt []byte, denom string) (found bool, err error) + // Get returns nil and an error which responds true to ormerrors.IsNotFound() if the record was not found. + Get(ctx context.Context, acocunt []byte, denom string) (*Balance, error) + List(ctx context.Context, prefixKey BalanceIndexKey, opts ...ormlist.Option) (BalanceIterator, error) + ListRange(ctx context.Context, from, to BalanceIndexKey, opts ...ormlist.Option) (BalanceIterator, error) + DeleteBy(ctx context.Context, prefixKey BalanceIndexKey) error + DeleteRange(ctx context.Context, from, to BalanceIndexKey) error + + doNotImplement() +} +``` + +This `BalanceTable` should be accessible from the `StateStore` interface (assuming our file is named `state.proto`) +via a `BalanceTable()` accessor method. If all the above example tables/singletons were in the same `state.proto`, +then `StateStore` would get generated like this: + +```go +type BankStore interface { + BalanceTable() BalanceTable + AccountTable() AccountTable + ParamsTable() ParamsTable + + doNotImplement() +} +``` + +So to work with the `BalanceTable` in a keeper method we could use code like this: + +```go +func (k keeper) AddBalance(ctx context.Context, acct []byte, denom string, amount uint64) error { + balance, err := k.db.BalanceTable().Get(ctx, acct, denom) + if err != nil && !ormerrors.IsNotFound(err) { + return err + } + + if balance == nil { + balance = &Balance{ + Account: acct, + Denom: denom, + Amount: amount, + } + } else { + balance.Amount = balance.Amount + amount + } + + return k.db.BalanceTable().Save(ctx, balance) +} +``` + +`List` methods take `IndexKey` parameters. For instance, `BalanceTable.List` takes `BalanceIndexKey`. `BalanceIndexKey` +let's represent index keys for the different indexes (primary and secondary) on the `Balance` table. The primary key +in the `Balance` table gets a struct `BalanceAccountDenomIndexKey` and the first index gets an index key `BalanceDenomIndexKey`. +If we wanted to list all the denoms and amounts that an account holds, we would use `BalanceAccountDenomIndexKey` +with a `List` query just on the account prefix. Ex: + +```go +it, err := keeper.db.BalanceTable().List(ctx, BalanceAccountDenomIndexKey{}.WithAccount(acct)) +``` diff --git a/versioned_docs/version-0.47/integrate/libraries/04-packages.md b/versioned_docs/version-0.47/integrate/libraries/04-packages.md new file mode 100644 index 000000000..7132b4138 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/libraries/04-packages.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 0 +--- + +# Packages + +The Cosmos SDK is a collection of Go modules. This section provides documentation on various packages that can used when developing a Cosmos SDK chain. +It lists all standalone Go modules that are part of the Cosmos SDK. + +:::tip +For more information on SDK modules, see the [SDK Modules](https://docs.cosmos.network/main/modules) section. +For more information on SDK tooling, see the [Tooling](https://docs.cosmos.network/main/tooling) section. +::: + +## Core + +* [Core](https://pkg.go.dev/cosmossdk.io/core) - Core library defining SDK interfaces ([ADR-063](https://docs.cosmos.network/main/architecture/adr-063-core-module-api)) +* [API](https://pkg.go.dev/cosmossdk.io/api) - API library containing generated SDK Pulsar API +* [Store](https://pkg.go.dev/cosmossdk.io/store) - Implementation of the Cosmos SDK store + +## State Management + +* [Collections](02-collections.md) - State management library +* [ORM](03-orm.md) - State management library + +## Automation + +* [Depinject](01-depinject.md) - Dependency injection framework +* [Client/v2](https://pkg.go.dev/cosmossdk.io/client/v2) - Library powering [AutoCLI](https://docs.cosmos.network/main/building-modules/autocli) + +## Utilities + +* [Log](https://pkg.go.dev/cosmossdk.io/log) - Logging library +* [Errors](https://pkg.go.dev/cosmossdk.io/errors) - Error handling library +* [Math](https://pkg.go.dev/cosmossdk.io/math) - Math library for SDK arithmetic operations + +## Example + +* [SimApp](https://pkg.go.dev/cosmossdk.io/simapp) - SimApp is **the** sample Cosmos SDK chain. This package should not be imported in your application. diff --git a/versioned_docs/version-0.47/integrate/libraries/_category_.json b/versioned_docs/version-0.47/integrate/libraries/_category_.json new file mode 100644 index 000000000..e91118d38 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/libraries/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Packages", + "position": 9, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/migrations/01-intro.md b/versioned_docs/version-0.47/integrate/migrations/01-intro.md index b27b294ea..82f1db580 100644 --- a/versioned_docs/version-0.47/integrate/migrations/01-intro.md +++ b/versioned_docs/version-0.47/integrate/migrations/01-intro.md @@ -12,4 +12,4 @@ Additionally, the SDK includes in-place migrations for its core modules. These i Migration from a version older than the last two major releases is not supported. -When migrating from a previous version, refer to the [`UPGRADING.md`](./02-upgrading.md) and the `CHANGELOG.md` of the version you are migrating to. +When migrating from a previous version, refer to the [`UPGRADING.md`](02-upgrading.md) and the `CHANGELOG.md` of the version you are migrating to. diff --git a/versioned_docs/version-0.47/integrate/migrations/02-upgrading.md b/versioned_docs/version-0.47/integrate/migrations/02-upgrading.md new file mode 100644 index 000000000..b5ed8e943 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/migrations/02-upgrading.md @@ -0,0 +1,612 @@ +# Upgrading Cosmos SDK + +This guide provides instructions for upgrading to specific versions of Cosmos SDK. +Note, always read the **SimApp** section for more information on application wiring updates. + +## [Unreleased] + +### Migration to CometBFT (Part 2) + +The Cosmos SDK has migrated in its previous versions, to CometBFT. +Some functions have been renamed to reflect the naming change. + +Following an exhaustive list: + +* `client.TendermintRPC` -> `client.CometRPC` +* `clitestutil.MockTendermintRPC` -> `clitestutil.MockCometRPC` +* `clitestutilgenutil.CreateDefaultTendermintConfig` -> `clitestutilgenutil.CreateDefaultCometConfig` +* Package `client/grpc/tmservice` -> `client/grpc/cmtservice` + +Additionally, the commands and flags mentioning `tendermint` have been renamed to `comet`. +However, these commands and flags is still supported for backward compatibility. + +For backward compatibility, the `**/tendermint/**` gRPC services are still supported. + +Additionally, the SDK is starting its abstraction from CometBFT Go types thorought the codebase: + +* The usage of CometBFT have been replaced to use the Cosmos SDK logger interface (`cosmossdk.io/log.Logger`). +* The usage of `github.com/cometbft/cometbft/libs/bytes.HexByte` have been replaced by `[]byte`. + +### Configuration + +A new tool have been created for migrating configuration of the SDK. Use the following command to migrate your configuration: + +```bash +simd config migrate v0.48 +``` + +More information about [confix](https://docs.cosmos.network/main/tooling/confix). + +#### Events + +The log section of abci.TxResult is not populated in the case of successful msg(s) execution. Instead a new attribute is added to all messages indicating the `msg_index` which identifies which events and attributes relate the same transaction + +#### gRPC-Web + +gRPC-Web is now listening to the same address as the gRPC Gateway API server (default: `localhost:1317`). +The possibility to listen to a different address has been removed, as well as its settings. +Use `confix` to clean-up your `app.toml`. A nginx (or alike) reverse-proxy can be set to keep the previous behavior. + +#### Database Support + +ClevelDB, BoltDB and BadgerDB are not supported anymore. To migrate from a unsupported database to a supported database please use the database migration tool. + +### Protobuf + +The SDK is in the process of removing all `gogoproto` annotations. + +#### Stringer + +The `gogoproto.goproto_stringer = false` annotation has been removed from most proto files. This means that the `String()` method is being generated for types that previously had this annotation. The generated `String()` method uses `proto.CompactTextString` for _stringifying_ structs. +[Verify](https://github.com/cosmos/cosmos-sdk/pull/13850#issuecomment-1328889651) the usage of the modified `String()` methods and double-check that they are not used in state-machine code. + +### SimApp + + + +#### Module Assertions + +Previously, all modules were required to be set in `OrderBeginBlockers`, `OrderEndBlockers` and `OrderInitGenesis / OrderExportGenesis` in `app.go` / `app_config.go`. +This is no longer the case, the assertion has been loosened to only require modules implementing, respectively, the `module.BeginBlockAppModule`, `module.EndBlockAppModule` and `module.HasGenesis` interfaces. + +#### Modules Keepers + +The following modules `NewKeeper` function now take a `KVStoreService` instead of a `StoreKey`: + +* `x/auth` +* `x/authz` +* `x/bank` +* `x/consensus` +* `x/distribution` +* `x/feegrant` +* `x/nft` + +User manually wiring their chain need to use the `runtime.NewKVStoreService` method to create a `KVStoreService` from a `StoreKey`: + +```diff +app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper( + appCodec, +- keys[consensusparamtypes.StoreKey] ++ runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +``` + +The following modules' `Keeper` methods now take in a `context.Context` instead of `sdk.Context`. Any module that has an interfaces for them (like "expected keepers") will need to update and re-generate mocks if needed: + +* `x/authz` +* `x/bank` +* `x/distribution` + +**Users using depinject do not need any changes, this is automatically done for them.** + +#### Logger + +The following modules `NewKeeper` function now take a `log.Logger`: + +* `x/bank` + +`depinject` users must now supply the logger through the main `depinject.Supply` function instead of passing it to `appBuilder.Build`. + +```diff +appConfig = depinject.Configs( + AppConfig, + depinject.Supply( + // supply the application options + appOpts, ++ logger, + ... +``` + +```diff +- app.App = appBuilder.Build(logger, db, traceStore, baseAppOptions...) ++ app.App = appBuilder.Build(db, traceStore, baseAppOptions...) +``` + +User manually wiring their chain need to add the logger argument when creating the keeper. + +#### Module Basics + +Previously, the `ModuleBasics` was a global variable that was used to register all modules's `AppModuleBasic` implementation. +The global variable has been removed and the basic module manager can be now created from the module manager. + +This is automatically done for depinject users, however for supplying different app module implementation, pass them via `depinject.Supply` in the main `AppConfig` (`app_config.go`): + +```go +depinject.Supply( + // supply custom module basics + map[string]module.AppModuleBasic{ + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + govtypes.ModuleName: gov.NewAppModuleBasic( + []govclient.ProposalHandler{ + paramsclient.ProposalHandler, + }, + ), + }, + ) +``` + +Users manually wiring their chain need to use the new `module.NewBasicManagerFromManager` function, after the module manager creation, and pass a `map[string]module.AppModuleBasic` as argument for optionally overridding some module's `AppModuleBasic`. + +### Packages + +#### Store + +References to `types/store.go` which contained aliases for store types have been remapped to point to appropriate store/types, hence the `types/store.go` file is no longer needed and has been removed. + +##### Extract Store to a standalone module + +The `store` module is extracted to have a separate go.mod file which allows it be a standalone module. +All the store imports are now renamed to use `cosmossdk.io/store` instead of `github.com/cosmos/cosmos-sdk/store` across the SDK. + +#### Client + +The return type of the interface method `TxConfig.SignModeHandler()` has been changed from `x/auth/signing.SignModeHandler` to `x/tx/signing.HandlerMap`. This change is transparent to most users as the `TxConfig` interface is typically implemented by private `x/auth/tx.config` struct (as returned by `auth.NewTxConfig`) which has been updated to return the new type. If users have implemented their own `TxConfig` interface, they will need to update their implementation to return the new type. + +### Modules + +#### `**all**` + +[RFC 001](https://docs.cosmos.network/main/rfc/rfc-001-tx-validation) has defined a simplification of the message validation process for modules. +The `sdk.Msg` interface has been updated to not require the implementation of the `ValidateBasic` method. +It is now recommended to validate message directly in the message server. When the validation is performed in the message server, the `ValidateBasic` method on a message is no longer required and can be removed. + +#### `x/auth` + +For ante handler construction via `ante.NewAnteHandler`, the field `ante.HandlerOptions.SignModeHandler` has been updated to `x/tx/signing/HandlerMap` from `x/auth/signing/SignModeHandler`. Callers typically fetch this value from `client.TxConfig.SignModeHandler()` (which is also changed) so this change should be transparent to most users. + +#### `x/capability` + +Capability was moved to [IBC-GO](https://github.com/cosmos/ibc-go). IBC V8 will contain the necessary changes to incorporate the new module location + +#### `x/gov` + +##### Expedited Proposals + +The `gov` v1 module has been updated to support the ability to expedite governance proposals. When a proposal is expedited, the voting period will be shortened to `ExpeditedVotingPeriod` parameter. An expedited proposal must have an higher voting threshold than a classic proposal, that threshold is defined with the `ExpeditedThreshold` parameter. + +##### Cancelling Proposals + +The `gov` module has been updated to support the ability to cancel governance proposals. When a proposal is canceled, all the deposits of the proposal are either burnt or sent to `ProposalCancelDest` address. The deposits burn rate will be determined by a new parameter called `ProposalCancelRatio` parameter. + +```text + 1. deposits * proposal_cancel_ratio will be burned or sent to `ProposalCancelDest` address , if `ProposalCancelDest` is empty then deposits will be burned. + 2. deposits * (1 - proposal_cancel_ratio) will be sent to depositors. +``` + +By default, the new `ProposalCancelRatio` parameter is set to 0.5 during migration and `ProposalCancelDest` is set to empty string (i.e. burnt). + +#### `x/evidence` + +##### Extract evidence to a standalone module + +The `x/evidence` module is extracted to have a separate go.mod file which allows it be a standalone module. +All the evidence imports are now renamed to use `cosmossdk.io/x/evidence` instead of `github.com/cosmos/cosmos-sdk/x/evidence` across the SDK. + +#### `x/nft` + +##### Extract nft to a standalone module + +The `x/nft` module is extracted to have a separate go.mod file which allows it to be a standalone module. + +#### x/feegrant + +##### Extract feegrant to a standalone module + +The `x/feegrant` module is extracted to have a separate go.mod file which allows it to be a standalone module. +All the feegrant imports are now renamed to use `cosmossdk.io/x/feegrant` instead of `github.com/cosmos/cosmos-sdk/x/feegrant` across the SDK. + +#### `x/upgrade` + +##### Extract upgrade to a standalone module + +The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module. +All the upgrade imports are now renamed to use `cosmossdk.io/x/upgrade` instead of `github.com/cosmos/cosmos-sdk/x/upgrade` across the SDK. + +## [v0.47.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.0) + +### Migration to CometBFT (Part 1) + +The Cosmos SDK has migrated to CometBFT, as its default consensus engine. +CometBFT is an implementation of the Tendermint consensus algorithm, and the successor of Tendermint Core. +Due to the import changes, this is a breaking change. Chains need to remove **entirely** their imports of Tendermint Core in their codebase, from direct and indirects imports in their `go.mod`. + +* Replace `github.com/tendermint/tendermint` by `github.com/cometbft/cometbft` +* Replace `github.com/tendermint/tm-db` by `github.com/cometbft/cometbft-db` +* Verify `github.com/tendermint/tendermint` is not an indirect or direct dependency +* Run `make proto-gen` + +Other than that, the migration should be seamless. +On the SDK side, clean-up of variables, functions to reflect the new name will only happen from v0.48 (part 2). + +Note: It is possible that these steps must first be performed by your dependencies before you can perform them on your own codebase. + +### Simulation + +Remove `RandomizedParams` from `AppModuleSimulation` interface. Previously, it used to generate random parameter changes during simulations, however, it does so through ParamChangeProposal which is now legacy. Since all modules were migrated, we can now safely remove this from `AppModuleSimulation` interface. + +Moreover, to support the `MsgUpdateParams` governance proposals for each modules, `AppModuleSimulation` now defines a `AppModule.ProposalMsgs` method in addition to `AppModule.ProposalContents`. That method defines the messages that can be used to submit a proposal and that should be tested in simulation. + +When a module has no proposal messages or proposal content to be tested by simulation, the `AppModule.ProposalMsgs` and `AppModule.ProposalContents` methods can be deleted. + +### gRPC + +A new gRPC service, `proto/cosmos/base/node/v1beta1/query.proto`, has been introduced +which exposes various operator configuration. App developers should be sure to +register the service with the gRPC-gateway service via +`nodeservice.RegisterGRPCGatewayRoutes` in their application construction, which +is typically found in `RegisterAPIRoutes`. + +### AppModule Interface + +Support for the `AppModule` `Querier`, `Route` and `LegacyQuerier` methods has been entirely removed from the `AppModule` +interface. This removes and fully deprecates all legacy queriers. All modules no longer support the REST API previously +known as the LCD, and the `sdk.Msg#Route` method won't be used anymore. + +Most other existing `AppModule` methods have been moved to extension interfaces in preparation for the migration +to the `cosmossdk.io/core/appmodule` API in the next release. Most `AppModule` implementations should not be broken +by this change. + +### SimApp + +The `simapp` package **should not be imported in your own app**. Instead, you should import the `runtime.AppI` interface, that defines an `App`, and use the [`simtestutil` package](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/testutil/sims) for application testing. + +#### App Wiring + +SimApp's `app_v2.go` is using [App Wiring](https://docs.cosmos.network/main/building-apps/app-go-v2), the dependency injection framework of the Cosmos SDK. +This means that modules are injected directly into SimApp thanks to a [configuration file](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app_config.go). +The previous behavior, without the dependency injection framework, is still present in [`app.go`](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app.go) and is not going anywhere. + +If you are using a `app.go` without dependency injection, add the following lines to your `app.go` in order to provide newer gRPC services: + +```go +autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules)) + +reflectionSvc, err := runtimeservices.NewReflectionService() +if err != nil { + panic(err) +} +reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc) +``` + +#### Constructor + +The constructor, `NewSimApp` has been simplified: + +* `NewSimApp` does not take encoding parameters (`encodingConfig`) as input, instead the encoding parameters are injected (when using app wiring), or directly created in the constructor. Instead, we can instantiate `SimApp` for getting the encoding configuration. +* `NewSimApp` now uses `AppOptions` for getting the home path (`homePath`) and the invariant checks period (`invCheckPeriod`). These were unnecessary given as arguments as they were already present in the `AppOptions`. + +#### Encoding + +`simapp.MakeTestEncodingConfig()` was deprecated and has been removed. Instead you can use the `TestEncodingConfig` from the `types/module/testutil` package. +This means you can replace your usage of `simapp.MakeTestEncodingConfig` in tests to `moduletestutil.MakeTestEncodingConfig`, which takes a series of relevant `AppModuleBasic` as input (the module being tested and any potential dependencies). + +#### Export + +`ExportAppStateAndValidators` takes an extra argument, `modulesToExport`, which is a list of module names to export. +That argument should be passed to the module maanager `ExportGenesisFromModules` method. + +#### Replaces + +The `GoLevelDB` version must pinned to `v1.0.1-0.20210819022825-2ae1ddf74ef7` in the application, following versions might cause unexpected behavior. +This can be done adding `replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7` to the `go.mod` file. + +* [issue #14949 on cosmos-sdk](https://github.com/cosmos/cosmos-sdk/issues/14949) +* [issue #25413 on go-ethereum](https://github.com/ethereum/go-ethereum/pull/25413) + +### Protobuf + +The SDK has migrated from `gogo/protobuf` (which is currently unmaintained), to our own maintained fork, [`cosmos/gogoproto`](https://github.com/cosmos/gogoproto). + +This means you should replace all imports of `github.com/gogo/protobuf` to `github.com/cosmos/gogoproto`. +This allows you to remove the replace directive `replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1` from your `go.mod` file. + +Please use the `ghcr.io/cosmos/proto-builder` image (version >= `0.11.5`) for generating protobuf files. + +See which buf commit for `cosmos/cosmos-sdk` to pin in your `buf.yaml` file [here](../tooling). + +#### Gogoproto Import Paths + +The SDK made a [patch fix](https://github.com/cosmos/gogoproto/pull/32) on its gogoproto repository to require that each proto file's package name matches its OS import path (relatively to a protobuf root import path, usually the root `proto/` folder, set by the `protoc -I` flag). + +For example, assuming you put all your proto files in subfolders inside your root `proto/` folder, then a proto file with package name `myapp.mymodule.v1` should be found in the `proto/myapp/mymodule/v1/` folder. If it is in another folder, the proto generation command will throw an error. + +If you are using a custom folder structure for your proto files, please reorganize them so that their OS path matches their proto package name. + +This is to allow the proto FileDescriptSets to be correctly registered, and this standardized OS import paths allows [Hubl](https://github.com/cosmos/cosmos-sdk/tree/main/tools/hubl) to reflectively talk to any chain. + +#### `{accepts,implements}_interface` proto annotations + +The SDK is normalizing the strings inside the Protobuf `accepts_interface` and `implements_interface` annotations. We require them to be fully-scoped names. They will soon be used by code generators like Pulsar and Telescope to match which messages can or cannot be packed inside `Any`s. + +Here are the following replacements that you need to perform on your proto files: + +```diff +- "Content" ++ "cosmos.gov.v1beta1.Content" +- "Authorization" ++ "cosmos.authz.v1beta1.Authorization" +- "sdk.Msg" ++ "cosmos.base.v1beta1.Msg" +- "AccountI" ++ "cosmos.auth.v1beta1.AccountI" +- "ModuleAccountI" ++ "cosmos.auth.v1beta1.ModuleAccountI" +- "FeeAllowanceI" ++ "cosmos.feegrant.v1beta1.FeeAllowanceI" +``` + +Please also check that in your own app's proto files that there are no single-word names for those two proto annotations. If so, then replace them with fully-qualified names, even though those names don't actually resolve to an actual protobuf entity. + +For more information, see the [encoding guide](../../develop/advanced-concepts/06-encoding.md). + +### Transactions + +#### Broadcast Mode + +Broadcast mode `block` was deprecated and has been removed. Please use `sync` mode +instead. When upgrading your tests from `block` to `sync` and checking for a +transaction code, you need to query the transaction first (with its hash) to get +the correct code. + +### Modules + +#### `**all**` + +`EventTypeMessage` events, with `sdk.AttributeKeyModule` and `sdk.AttributeKeySender` are now emitted directly at message excecution (in `baseapp`). +This means that the following boilerplate should be removed from all your custom modules: + +```go +ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, `signer/sender`), + ), +) +``` + +The module name is assumed by `baseapp` to be the second element of the message route: `"cosmos.bank.v1beta1.MsgSend" -> "bank"`. +In case a module does not follow the standard message path, (e.g. IBC), it is advised to keep emitting the module name event. +`Baseapp` only emits that event if the module has not already done so. + +#### `x/params` + +The `params` module was deprecated since v0.46. The Cosmos SDK has migrated away from `x/params` for its own modules. +Cosmos SDK modules now store their parameters directly in its repective modules. +The `params` module will be removed in `v0.48`, as mentioned [in v0.46 release](https://github.com/cosmos/cosmos-sdk/blob/v0.46.1/UPGRADING.md#xparams). It is strongly encouraged to migrate away from `x/params` before `v0.48`. + +When performing a chain migration, the params table must be initizalied manually. This was done in the modules keepers in previous versions. +Have a look at `simapp.RegisterUpgradeHandlers()` for an example. + +#### `x/gov` + +##### Minimum Proposal Deposit At Time of Submission + +The `gov` module has been updated to support a minimum proposal deposit at submission time. It is determined by a new +parameter called `MinInitialDepositRatio`. When multiplied by the existing `MinDeposit` parameter, it produces +the necessary proportion of coins needed at the proposal submission time. The motivation for this change is to prevent proposal spamming. + +By default, the new `MinInitialDepositRatio` parameter is set to zero during migration. The value of zero signifies that this +feature is disabled. If chains wish to utilize the minimum proposal deposits at time of submission, the migration logic needs to be +modified to set the new parameter to the desired value. + +##### New Proposal.Proposer field + +The `Proposal` proto has been updated with proposer field. For proposal state migraton developers can call `v4.AddProposerAddressToProposal` in their upgrade handler to update all existing proposal and make them compatible and **this migration is optional**. + +```go +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" +) + +func (app SimApp) RegisterUpgradeHandlers() { + app.UpgradeKeeper.SetUpgradeHandler(UpgradeName, + func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // this migration is optional + // add proposal ids with proposers which are active (deposit or voting period) + proposals := make(map[uint64]string) + proposals[1] = "cosmos1luyncewxk4lm24k6gqy8y5dxkj0klr4tu0lmnj" ... + v4.AddProposerAddressToProposal(ctx, sdk.NewKVStoreKey(v4.ModuleName), app.appCodec, proposals) + return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) + }) +} + +``` + +#### `x/consensus` + +Introducing a new `x/consensus` module to handle managing Tendermint consensus +parameters. For migration it is required to call a specific migration to migrate +existing parameters from the deprecated `x/params` to `x/consensus` module. App +developers should ensure to call `baseapp.MigrateParams` in their upgrade handler. + +Example: + +```go +func (app SimApp) RegisterUpgradeHandlers() { + ----> baseAppLegacySS := app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()) <---- + + app.UpgradeKeeper.SetUpgradeHandler( + UpgradeName, + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // Migrate Tendermint consensus parameters from x/params module to a + // dedicated x/consensus module. + ----> baseapp.MigrateParams(ctx, baseAppLegacySS, &app.ConsensusParamsKeeper) <---- + + // ... + + return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) + }, + ) + + // ... +} +``` + +The old params module is required to still be imported in your app.go in order to handle this migration. + +##### `app.go` changes + +When using an `app.go` without App Wiring, the following changes are required: + +```diff +- bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable())) ++ app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[consensusparamstypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String()) ++ bApp.SetParamStore(&app.ConsensusParamsKeeper) +``` + +When using App Wiring, the paramater store is automatically set for you. + +#### `x/nft` + +The SDK does not validate anymore the `classID` and `nftID` of an NFT, for extra flexibility in your NFT implementation. +This means chain developers need to validate the `classID` and `nftID` of an NFT. + +### Ledger + +Ledger support has been generalized to enable use of different apps and keytypes that use `secp256k1`. The Ledger interface remains the same, but it can now be provided through the Keyring `Options`, allowing higher-level chains to connect to different Ledger apps or use custom implementations. In addition, higher-level chains can provide custom key implementations around the Ledger public key, to enable greater flexibility with address generation and signing. + +This is not a breaking change, as all values will default to use the standard Cosmos app implementation unless specified otherwise. + +## [v0.46.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.0) + +### Go API Changes + +The `replace google.golang.org/grpc` directive can be removed from the `go.mod`, it is no more required to block the version. + +A few packages that were deprecated in the previous version are now removed. + +For instance, the REST API, deprecated in v0.45, is now removed. If you have not migrated yet, please follow the [instructions](https://docs.cosmos.network/v0.45/migrations/rest.html). + +To improve clarity of the API, some renaming and improvements has been done: + +| Package | Previous | Current | +| --------- | ---------------------------------- | ------------------------------------ | +| `simapp` | `encodingConfig.Marshaler` | `encodingConfig.Codec` | +| `simapp` | `FundAccount`, `FundModuleAccount` | Functions moved to `x/bank/testutil` | +| `types` | `AccAddressFromHex` | `AccAddressFromHexUnsafe` | +| `x/auth` | `MempoolFeeDecorator` | Use `DeductFeeDecorator` instead | +| `x/bank` | `AddressFromBalancesStore` | `AddressAndDenomFromBalancesStore` | +| `x/gov` | `keeper.DeleteDeposits` | `keeper.DeleteAndBurnDeposits` | +| `x/gov` | `keeper.RefundDeposits` | `keeper.RefundAndDeleteDeposits` | +| `x/{mod}` | package `legacy` | package `migrations` | + +For the exhaustive list of API renaming, please refer to the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/main/CHANGELOG.md). + +#### new packages + +Additionally, new packages have been introduced in order to further split the codebase. Aliases are available for a new API breaking migration, but it is encouraged to migrate to this new packages: + +* `errors` should replace `types/errors` when registering errors or wrapping SDK errors. +* `math` contains the `Int` or `Uint` types that are used in the SDK. +* `x/nft` an NFT base module. +* `x/group` a group module allowing to create DAOs, multisig and policies. Greatly composes with `x/authz`. + +#### `x/authz` + +* `authz.NewMsgGrant` `expiration` is now a pointer. When `nil` is used, then no expiration will be set (grant won't expire). +* `authz.NewGrant` takes a new argument: block time, to correctly validate expire time. + +### Keyring + +The keyring has been refactored in v0.46. + +* The `Unsafe*` interfaces have been removed from the keyring package. Please use interface casting if you wish to access those unsafe functions. +* The keys' implementation has been refactored to be serialized as proto. +* `keyring.NewInMemory` and `keyring.New` takes now a `codec.Codec`. +* Take `keyring.Record` instead of `Info` as first argument in: + * `MkConsKeyOutput` + * `MkValKeyOutput` + * `MkAccKeyOutput` +* Rename: + * `SavePubKey` to `SaveOfflineKey` and remove the `algo` argument. + * `NewMultiInfo`, `NewLedgerInfo` to `NewLegacyMultiInfo`, `newLegacyLedgerInfo` respectively. + * `NewOfflineInfo` to `newLegacyOfflineInfo` and move it to `migration_test.go`. + +### PostHandler + +A `postHandler` is like an `antehandler`, but is run _after_ the `runMsgs` execution. It is in the same store branch that `runMsgs`, meaning that both `runMsgs` and `postHandler`. This allows to run a custom logic after the execution of the messages. + +### IAVL + +v0.19.0 IAVL introduces a new "fast" index. This index represents the latest state of the +IAVL laid out in a format that preserves data locality by key. As a result, it allows for faster queries and iterations +since data can now be read in lexicographical order that is frequent for Cosmos-SDK chains. + +The first time the chain is started after the upgrade, the aforementioned index is created. The creation process +might take time and depends on the size of the latest state of the chain. For example, Osmosis takes around 15 minutes to rebuild the index. + +While the index is being created, node operators can observe the following in the logs: +"Upgrading IAVL storage for faster queries + execution on the live state. This may take a while". The store +key is appended to the message. The message is printed for every module that has a non-transient store. +As a result, it gives a good indication of the progress of the upgrade. + +There is also downgrade and re-upgrade protection. If a node operator chooses to downgrade to IAVL pre-fast index, and then upgrade again, the index is rebuilt from scratch. This implementation detail should not be relevant in most cases. It was added as a safeguard against operator +mistakes. + +### Modules + +#### `x/params` + +* The `x/params` module has been depreacted in favour of each module housing and providing way to modify their parameters. Each module that has parameters that are changable during runtime have an authority, the authority can be a module or user account. The Cosmos SDK team recommends migrating modules away from using the param module. An example of how this could look like can be found [here](https://github.com/cosmos/cosmos-sdk/pull/12363). +* The Param module will be maintained until April 18, 2023. At this point the module will reach end of life and be removed from the Cosmos SDK. + +#### `x/gov` + +The `gov` module has been greatly improved. The previous API has been moved to `v1beta1` while the new implementation is called `v1`. + +In order to submit a proposal with `submit-proposal` you now need to pass a `proposal.json` file. +You can still use the old way by using `submit-legacy-proposal`. This is not recommended. +More information can be found in the gov module [client documentation](https://docs.cosmos.network/v0.46/modules/gov/07_client.html). + +#### `x/staking` + +The `staking module` added a new message type to cancel unbonding delegations. Users that have unbonded by accident or wish to cancel a undelegation can now specify the amount and valdiator they would like to cancel the unbond from + +### Protobuf + +The `third_party/proto` folder that existed in [previous version](https://github.com/cosmos/cosmos-sdk/tree/v0.45.3/third_party/proto) now does not contains directly the [proto files](https://github.com/cosmos/cosmos-sdk/tree/release/v0.46.x/third_party/proto). + +Instead, the SDK uses [`buf`](https://buf.build). Clients should have their own [`buf.yaml`](https://docs.buf.build/configuration/v1/buf-yaml) with `buf.build/cosmos/cosmos-sdk` as dependency, in order to avoid having to copy paste these files. + +The protos can as well be downloaded using `buf export buf.build/cosmos/cosmos-sdk:8cb30a2c4de74dc9bd8d260b1e75e176 --output `. + +Cosmos message protobufs should be extended with `cosmos.msg.v1.signer`: + +```protobuf +message MsgSetWithdrawAddress { + option (cosmos.msg.v1.signer) = "delegator_address"; ++ + + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string withdraw_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} +``` + +When clients interract with a node they are required to set a codec in in the grpc.Dial. More information can be found in this [doc](https://docs.cosmos.network/v0.46/run-node/interact-node.html#programmatically-via-go). diff --git a/versioned_docs/version-0.47/integrate/migrations/_category_.json b/versioned_docs/version-0.47/integrate/migrations/_category_.json index add3887b8..258dc810c 100644 --- a/versioned_docs/version-0.47/integrate/migrations/_category_.json +++ b/versioned_docs/version-0.47/integrate/migrations/_category_.json @@ -1,5 +1,5 @@ { "label": "SDK Migrations", - "position": 6, + "position": 3, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.46/integrate/modules/README.md b/versioned_docs/version-0.47/integrate/modules/README.md similarity index 90% rename from versioned_docs/version-0.46/integrate/modules/README.md rename to versioned_docs/version-0.47/integrate/modules/README.md index 2270e78eb..c5a8cc63d 100644 --- a/versioned_docs/version-0.46/integrate/modules/README.md +++ b/versioned_docs/version-0.47/integrate/modules/README.md @@ -21,6 +21,9 @@ Here are some production-grade modules that can be used in Cosmos SDK applicatio * [Staking](staking/README.md) - Proof-of-Stake layer for public blockchains. * [Upgrade](upgrade/README.md) - Software upgrades handling and coordination. * [NFT](nft/README.md) - NFT module implemented based on [ADR43](https://docs.cosmos.network/main/architecture/adr-043-nft-module.html). +* [Consensus](consensus/README.md) - Consensus module for modifying CometBFT's ABCI consensus params. +* [Circuit](circuit/README.md) - Circuit breaker module for pausing messages. +* [Genutil](genutil/README.md) - Genesis utilities for the Cosmos SDK. To learn more about the process of building modules, visit the [building modules reference documentation](https://docs.cosmos.network/main/building-modules/intro). diff --git a/versioned_docs/version-0.47/integrate/modules/_category_.json b/versioned_docs/version-0.47/integrate/modules/_category_.json index 6038c7662..9aac4ff6e 100644 --- a/versioned_docs/version-0.47/integrate/modules/_category_.json +++ b/versioned_docs/version-0.47/integrate/modules/_category_.json @@ -1,5 +1,5 @@ { - "label": "SDK Modules", - "position": 7, + "label": "List of SDK Modules", + "position": 2, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/modules/auth/1-vesting.md b/versioned_docs/version-0.47/integrate/modules/auth/1-vesting.md new file mode 100644 index 000000000..62619ede0 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/auth/1-vesting.md @@ -0,0 +1,618 @@ +--- +sidebar_position: 1 +--- + +# `x/auth/vesting` + + +* [Intro and Requirements](#intro-and-requirements) +* [Note](#note) +* [Vesting Account Types](#vesting-account-types) + * [BaseVestingAccount](#basevestingaccount) + * [ContinuousVestingAccount](#continuousvestingaccount) + * [DelayedVestingAccount](#delayedvestingaccount) + * [Period](#period) + * [PeriodicVestingAccount](#periodicvestingaccount) + * [PermanentLockedAccount](#permanentlockedaccount) +* [Vesting Account Specification](#vesting-account-specification) + * [Determining Vesting & Vested Amounts](#determining-vesting--vested-amounts) + * [Periodic Vesting Accounts](#periodic-vesting-accounts) + * [Transferring/Sending](#transferringsending) + * [Delegating](#delegating) + * [Undelegating](#undelegating) +* [Keepers & Handlers](#keepers--handlers) +* [Genesis Initialization](#genesis-initialization) +* [Examples](#examples) + * [Simple](#simple) + * [Slashing](#slashing) + * [Periodic Vesting](#periodic-vesting) +* [Glossary](#glossary) + +## Intro and Requirements + +This specification defines the vesting account implementation that is used by the Cosmos Hub. The requirements for this vesting account is that it should be initialized during genesis with a starting balance `X` and a vesting end time `ET`. A vesting account may be initialized with a vesting start time `ST` and a number of vesting periods `P`. If a vesting start time is included, the vesting period does not begin until start time is reached. If vesting periods are included, the vesting occurs over the specified number of periods. + +For all vesting accounts, the owner of the vesting account is able to delegate and undelegate from validators, however they cannot transfer coins to another account until those coins are vested. This specification allows for four different kinds of vesting: + +* Delayed vesting, where all coins are vested once `ET` is reached. +* Continous vesting, where coins begin to vest at `ST` and vest linearly with respect to time until `ET` is reached +* Periodic vesting, where coins begin to vest at `ST` and vest periodically according to number of periods and the vesting amount per period. The number of periods, length per period, and amount per period are configurable. A periodic vesting account is distinguished from a continuous vesting account in that coins can be released in staggered tranches. For example, a periodic vesting account could be used for vesting arrangements where coins are relased quarterly, yearly, or over any other function of tokens over time. +* Permanent locked vesting, where coins are locked forever. Coins in this account can still be used for delegating and for governance votes even while locked. + +## Note + +Vesting accounts can be initialized with some vesting and non-vesting coins. The non-vesting coins would be immediately transferable. DelayedVesting ContinuousVesting, PeriodicVesting and PermenantVesting accounts can be created with normal messages after genesis. Other types of vesting accounts must be created at genesis, or as part of a manual network upgrade. The current specification only allows for _unconditional_ vesting (ie. there is no possibility of reaching `ET` and +having coins fail to vest). + +## Vesting Account Types + +```go +// VestingAccount defines an interface that any vesting account type must +// implement. +type VestingAccount interface { + Account + + GetVestedCoins(Time) Coins + GetVestingCoins(Time) Coins + + // TrackDelegation performs internal vesting accounting necessary when + // delegating from a vesting account. It accepts the current block time, the + // delegation amount and balance of all coins whose denomination exists in + // the account's original vesting balance. + TrackDelegation(Time, Coins, Coins) + + // TrackUndelegation performs internal vesting accounting necessary when a + // vesting account performs an undelegation. + TrackUndelegation(Coins) + + GetStartTime() int64 + GetEndTime() int64 +} +``` + +### BaseVestingAccount + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L11-L35 +``` + +### ContinuousVestingAccount + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L37-L46 +``` + +### DelayedVestingAccount + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L48-L57 +``` + +### Period + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L59-L69 +``` + +```go +// Stores all vesting periods passed as part of a PeriodicVestingAccount +type Periods []Period + +``` + +### PeriodicVestingAccount + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L71-L81 +``` + +In order to facilitate less ad-hoc type checking and assertions and to support flexibility in account balance usage, the existing `x/bank` `ViewKeeper` interface is updated to contain the following: + +```go +type ViewKeeper interface { + // ... + + // Calculates the total locked account balance. + LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + + // Calculates the total spendable balance that can be sent to other accounts. + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} +``` + +### PermanentLockedAccount + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/vesting/v1beta1/vesting.proto#L83-L94 +``` + +## Vesting Account Specification + +Given a vesting account, we define the following in the proceeding operations: + +* `OV`: The original vesting coin amount. It is a constant value. +* `V`: The number of `OV` coins that are still _vesting_. It is derived by +`OV`, `StartTime` and `EndTime`. This value is computed on demand and not on a per-block basis. +* `V'`: The number of `OV` coins that are _vested_ (unlocked). This value is computed on demand and not a per-block basis. +* `DV`: The number of delegated _vesting_ coins. It is a variable value. It is stored and modified directly in the vesting account. +* `DF`: The number of delegated _vested_ (unlocked) coins. It is a variable value. It is stored and modified directly in the vesting account. +* `BC`: The number of `OV` coins less any coins that are transferred +(which can be negative or delegated). It is considered to be balance of the embedded base account. It is stored and modified directly in the vesting account. + +### Determining Vesting & Vested Amounts + +It is important to note that these values are computed on demand and not on a mandatory per-block basis (e.g. `BeginBlocker` or `EndBlocker`). + +#### Continuously Vesting Accounts + +To determine the amount of coins that are vested for a given block time `T`, the +following is performed: + +1. Compute `X := T - StartTime` +2. Compute `Y := EndTime - StartTime` +3. Compute `V' := OV * (X / Y)` +4. Compute `V := OV - V'` + +Thus, the total amount of _vested_ coins is `V'` and the remaining amount, `V`, +is _vesting_. + +```go +func (cva ContinuousVestingAccount) GetVestedCoins(t Time) Coins { + if t <= cva.StartTime { + // We must handle the case where the start time for a vesting account has + // been set into the future or when the start of the chain is not exactly + // known. + return ZeroCoins + } else if t >= cva.EndTime { + return cva.OriginalVesting + } + + x := t - cva.StartTime + y := cva.EndTime - cva.StartTime + + return cva.OriginalVesting * (x / y) +} + +func (cva ContinuousVestingAccount) GetVestingCoins(t Time) Coins { + return cva.OriginalVesting - cva.GetVestedCoins(t) +} +``` + +### Periodic Vesting Accounts + +Periodic vesting accounts require calculating the coins released during each period for a given block time `T`. Note that multiple periods could have passed when calling `GetVestedCoins`, so we must iterate over each period until the end of that period is after `T`. + +1. Set `CT := StartTime` +2. Set `V' := 0` + +For each Period P: + + 1. Compute `X := T - CT` + 2. IF `X >= P.Length` + 1. Compute `V' += P.Amount` + 2. Compute `CT += P.Length` + 3. ELSE break + 3. Compute `V := OV - V'` + +```go +func (pva PeriodicVestingAccount) GetVestedCoins(t Time) Coins { + if t < pva.StartTime { + return ZeroCoins + } + ct := pva.StartTime // The start of the vesting schedule + vested := 0 + periods = pva.GetPeriods() + for _, period := range periods { + if t - ct < period.Length { + break + } + vested += period.Amount + ct += period.Length // increment ct to the start of the next vesting period + } + return vested +} + +func (pva PeriodicVestingAccount) GetVestingCoins(t Time) Coins { + return pva.OriginalVesting - cva.GetVestedCoins(t) +} +``` + +#### Delayed/Discrete Vesting Accounts + +Delayed vesting accounts are easier to reason about as they only have the full amount vesting up until a certain time, then all the coins become vested (unlocked). This does not include any unlocked coins the account may have initially. + +```go +func (dva DelayedVestingAccount) GetVestedCoins(t Time) Coins { + if t >= dva.EndTime { + return dva.OriginalVesting + } + + return ZeroCoins +} + +func (dva DelayedVestingAccount) GetVestingCoins(t Time) Coins { + return dva.OriginalVesting - dva.GetVestedCoins(t) +} +``` + +### Transferring/Sending + +At any given time, a vesting account may transfer: `min((BC + DV) - V, BC)`. + +In other words, a vesting account may transfer the minimum of the base account balance and the base account balance plus the number of currently delegated vesting coins less the number of coins vested so far. + +However, given that account balances are tracked via the `x/bank` module and that we want to avoid loading the entire account balance, we can instead determine the locked balance, which can be defined as `max(V - DV, 0)`, and infer the spendable balance from that. + +```go +func (va VestingAccount) LockedCoins(t Time) Coins { + return max(va.GetVestingCoins(t) - va.DelegatedVesting, 0) +} +``` + +The `x/bank` `ViewKeeper` can then provide APIs to determine locked and spendable coins for any account: + +```go +func (k Keeper) LockedCoins(ctx Context, addr AccAddress) Coins { + acc := k.GetAccount(ctx, addr) + if acc != nil { + if acc.IsVesting() { + return acc.LockedCoins(ctx.BlockTime()) + } + } + + // non-vesting accounts do not have any locked coins + return NewCoins() +} +``` + +#### Keepers/Handlers + +The corresponding `x/bank` keeper should appropriately handle sending coins based on if the account is a vesting account or not. + +```go +func (k Keeper) SendCoins(ctx Context, from Account, to Account, amount Coins) { + bc := k.GetBalances(ctx, from) + v := k.LockedCoins(ctx, from) + + spendable := bc - v + newCoins := spendable - amount + assert(newCoins >= 0) + + from.SetBalance(newCoins) + to.AddBalance(amount) + + // save balances... +} +``` + +### Delegating + +For a vesting account attempting to delegate `D` coins, the following is performed: + +1. Verify `BC >= D > 0` +2. Compute `X := min(max(V - DV, 0), D)` (portion of `D` that is vesting) +3. Compute `Y := D - X` (portion of `D` that is free) +4. Set `DV += X` +5. Set `DF += Y` + +```go +func (va VestingAccount) TrackDelegation(t Time, balance Coins, amount Coins) { + assert(balance <= amount) + x := min(max(va.GetVestingCoins(t) - va.DelegatedVesting, 0), amount) + y := amount - x + + va.DelegatedVesting += x + va.DelegatedFree += y +} +``` + +**Note** `TrackDelegation` only modifies the `DelegatedVesting` and `DelegatedFree` fields, so upstream callers MUST modify the `Coins` field by subtracting `amount`. + +#### Keepers/Handlers + +```go +func DelegateCoins(t Time, from Account, amount Coins) { + if isVesting(from) { + from.TrackDelegation(t, amount) + } else { + from.SetBalance(sc - amount) + } + + // save account... +} +``` + +### Undelegating + +For a vesting account attempting to undelegate `D` coins, the following is performed: + +> NOTE: `DV < D` and `(DV + DF) < D` may be possible due to quirks in the rounding of delegation/undelegation logic. + +1. Verify `D > 0` +2. Compute `X := min(DF, D)` (portion of `D` that should become free, prioritizing free coins) +3. Compute `Y := min(DV, D - X)` (portion of `D` that should remain vesting) +4. Set `DF -= X` +5. Set `DV -= Y` + +```go +func (cva ContinuousVestingAccount) TrackUndelegation(amount Coins) { + x := min(cva.DelegatedFree, amount) + y := amount - x + + cva.DelegatedFree -= x + cva.DelegatedVesting -= y +} +``` + +**Note** `TrackUnDelegation` only modifies the `DelegatedVesting` and `DelegatedFree` fields, so upstream callers MUST modify the `Coins` field by adding `amount`. + +**Note**: If a delegation is slashed, the continuous vesting account ends up with an excess `DV` amount, even after all its coins have vested. This is because undelegating free coins are prioritized. + +**Note**: The undelegation (bond refund) amount may exceed the delegated vesting (bond) amount due to the way undelegation truncates the bond refund, which can increase the validator's exchange rate (tokens/shares) slightly if the undelegated tokens are non-integral. + +#### Keepers/Handlers + +```go +func UndelegateCoins(to Account, amount Coins) { + if isVesting(to) { + if to.DelegatedFree + to.DelegatedVesting >= amount { + to.TrackUndelegation(amount) + // save account ... + } + } else { + AddBalance(to, amount) + // save account... + } +} +``` + +## Keepers & Handlers + +The `VestingAccount` implementations reside in `x/auth`. However, any keeper in a module (e.g. staking in `x/staking`) wishing to potentially utilize any vesting coins, must call explicit methods on the `x/bank` keeper (e.g. `DelegateCoins`) opposed to `SendCoins` and `SubtractCoins`. + +In addition, the vesting account should also be able to spend any coins it receives from other users. Thus, the bank module's `MsgSend` handler should error if a vesting account is trying to send an amount that exceeds their unlocked coin amount. + +See the above specification for full implementation details. + +## Genesis Initialization + +To initialize both vesting and non-vesting accounts, the `GenesisAccount` struct includes new fields: `Vesting`, `StartTime`, and `EndTime`. Accounts meant to be of type `BaseAccount` or any non-vesting type have `Vesting = false`. The genesis initialization logic (e.g. `initFromGenesisState`) must parse and return the correct accounts accordingly based off of these fields. + +```go +type GenesisAccount struct { + // ... + + // vesting account fields + OriginalVesting sdk.Coins `json:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting"` + StartTime int64 `json:"start_time"` + EndTime int64 `json:"end_time"` +} + +func ToAccount(gacc GenesisAccount) Account { + bacc := NewBaseAccount(gacc) + + if gacc.OriginalVesting > 0 { + if ga.StartTime != 0 && ga.EndTime != 0 { + // return a continuous vesting account + } else if ga.EndTime != 0 { + // return a delayed vesting account + } else { + // invalid genesis vesting account provided + panic() + } + } + + return bacc +} +``` + +## Examples + +### Simple + +Given a continuous vesting account with 10 vesting coins. + +```text +OV = 10 +DF = 0 +DV = 0 +BC = 10 +V = 10 +V' = 0 +``` + +1. Immediately receives 1 coin + + ```text + BC = 11 + ``` + +2. Time passes, 2 coins vest + + ```text + V = 8 + V' = 2 + ``` + +3. Delegates 4 coins to validator A + + ```text + DV = 4 + BC = 7 + ``` + +4. Sends 3 coins + + ```text + BC = 4 + ``` + +5. More time passes, 2 more coins vest + + ```text + V = 6 + V' = 4 + ``` + +6. Sends 2 coins. At this point the account cannot send anymore until further +coins vest or it receives additional coins. It can still however, delegate. + + ```text + BC = 2 + ``` + +### Slashing + +Same initial starting conditions as the simple example. + +1. Time passes, 5 coins vest + + ```text + V = 5 + V' = 5 + ``` + +2. Delegate 5 coins to validator A + + ```text + DV = 5 + BC = 5 + ``` + +3. Delegate 5 coins to validator B + + ```text + DF = 5 + BC = 0 + ``` + +4. Validator A gets slashed by 50%, making the delegation to A now worth 2.5 coins +5. Undelegate from validator A (2.5 coins) + + ```text + DF = 5 - 2.5 = 2.5 + BC = 0 + 2.5 = 2.5 + ``` + +6. Undelegate from validator B (5 coins). The account at this point can only +send 2.5 coins unless it receives more coins or until more coins vest. +It can still however, delegate. + + ```text + DV = 5 - 2.5 = 2.5 + DF = 2.5 - 2.5 = 0 + BC = 2.5 + 5 = 7.5 + ``` + + Notice how we have an excess amount of `DV`. + +### Periodic Vesting + +A vesting account is created where 100 tokens will be released over 1 year, with +1/4 of tokens vesting each quarter. The vesting schedule would be as follows: + +```yaml +Periods: +- amount: 25stake, length: 7884000 +- amount: 25stake, length: 7884000 +- amount: 25stake, length: 7884000 +- amount: 25stake, length: 7884000 +``` + +```text +OV = 100 +DF = 0 +DV = 0 +BC = 100 +V = 100 +V' = 0 +``` + +1. Immediately receives 1 coin + + ```text + BC = 101 + ``` + +2. Vesting period 1 passes, 25 coins vest + + ```text + V = 75 + V' = 25 + ``` + +3. During vesting period 2, 5 coins are transfered and 5 coins are delegated + + ```text + DV = 5 + BC = 91 + ``` + +4. Vesting period 2 passes, 25 coins vest + + ```text + V = 50 + V' = 50 + ``` + +## Glossary + +* OriginalVesting: The amount of coins (per denomination) that are initially +part of a vesting account. These coins are set at genesis. +* StartTime: The BFT time at which a vesting account starts to vest. +* EndTime: The BFT time at which a vesting account is fully vested. +* DelegatedFree: The tracked amount of coins (per denomination) that are +delegated from a vesting account that have been fully vested at time of delegation. +* DelegatedVesting: The tracked amount of coins (per denomination) that are +delegated from a vesting account that were vesting at time of delegation. +* ContinuousVestingAccount: A vesting account implementation that vests coins +linearly over time. +* DelayedVestingAccount: A vesting account implementation that only fully vests +all coins at a given time. +* PeriodicVestingAccount: A vesting account implementation that vests coins +according to a custom vesting schedule. +* PermanentLockedAccount: It does not ever release coins, locking them indefinitely. +Coins in this account can still be used for delegating and for governance votes even while locked. + + +## CLI + +A user can query and interact with the `vesting` module using the CLI. + +### Transactions + +The `tx` commands allow users to interact with the `vesting` module. + +```bash +simd tx vesting --help +``` + +#### create-periodic-vesting-account + +The `create-periodic-vesting-account` command creates a new vesting account funded with an allocation of tokens, where a sequence of coins and period length in seconds. Periods are sequential, in that the duration of of a period only starts at the end of the previous period. The duration of the first period starts upon account creation. + +```bash +simd tx vesting create-periodic-vesting-account [to_address] [periods_json_file] [flags] +``` + +Example: + +```bash +simd tx vesting create-periodic-vesting-account cosmos1.. periods.json +``` + +#### create-vesting-account + +The `create-vesting-account` command creates a new vesting account funded with an allocation of tokens. The account can either be a delayed or continuous vesting account, which is determined by the '--delayed' flag. All vesting accouts created will have their start time set by the committed block's time. The end_time must be provided as a UNIX epoch timestamp. + +```bash +simd tx vesting create-vesting-account [to_address] [amount] [end_time] [flags] +``` + +Example: + +```bash +simd tx vesting create-vesting-account cosmos1.. 100stake 2592000 +``` diff --git a/versioned_docs/version-0.47/integrate/modules/auth/2-tx.md b/versioned_docs/version-0.47/integrate/modules/auth/2-tx.md new file mode 100644 index 000000000..0460f69d8 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/auth/2-tx.md @@ -0,0 +1,266 @@ +--- +sidebar_position: 1 +--- + +# `x/auth/tx` + +:::note + +### Pre-requisite Readings + +* [Transactions](https://docs.cosmos.network/main/core/transactions#transaction-generation) +* [Encoding](https://docs.cosmos.network/main/core/encoding#transaction-encoding) + +::: + +## Abstract + +This document specifies the `x/auth/tx` package of the Cosmos SDK. + +This package represents the Cosmos SDK implementation of the `client.TxConfig`, `client.TxBuilder`, `client.TxEncoder` and `client.TxDecoder` interfaces. + +## Contents + +* [Transactions](#transactions) + * [`TxConfig`](#txconfig) + * [`TxBuilder`](#txbuilder) + * [`TxEncoder`/ `TxDecoder`](#txencoder-txdecoder) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + +## Transactions + +### `TxConfig` + +`client.TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. +The interface defines a set of methods for creating a `client.TxBuilder`. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/tx_config.go#L25-L31 +``` + +The default implementation of `client.TxConfig` is instantiated by `NewTxConfig` in `x/auth/tx` module. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/tx/config.go#L22-L28 +``` + +### `TxBuilder` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/tx_config.go#L33-L50 +``` + +The [`client.TxBuilder`](https://docs.cosmos.network/main/core/transactions#transaction-generation) interface is as well implemented by `x/auth/tx`. +A `client.TxBuilder` can be accessed with `TxConfig.NewTxBuilder()`. + +### `TxEncoder`/ `TxDecoder` + +More information about `TxEncoder` and `TxDecoder` can be found [here](https://docs.cosmos.network/main/core/encoding#transaction-encoding). + +## Client + +### CLI + +#### Query + +The `x/auth/tx` module provides a CLI command to query any transaction, given its hash, transaction sequence or signature. + +Without any argument, the command will query the transaction using the transaction hash. + +```shell +simd query tx DFE87B78A630C0EFDF76C80CD24C997E252792E0317502AE1A02B9809F0D8685 +``` + +When querying a transaction from an account given its sequence, use the `--type=acc_seq` flag: + +```shell +simd query tx --type=acc_seq cosmos1u69uyr6v9qwe6zaaeaqly2h6wnedac0xpxq325/1 +``` + +When querying a transaction given its signature, use the `--type=signature` flag: + +```shell +simd query tx --type=signature Ofjvgrqi8twZfqVDmYIhqwRLQjZZ40XbxEamk/veH3gQpRF0hL2PH4ejRaDzAX+2WChnaWNQJQ41ekToIi5Wqw== +``` + +When querying a transaction given its events, use the `--type=events` flag: + +```shell +simd query txs --events 'message.sender=cosmos...' --page 1 --limit 30 +``` + +The `x/auth/block` module provides a CLI command to query any block, given its hash, height, or events. + +When querying a block by its hash, use the `--type=hash` flag: + +```shell +simd query block --type=hash DFE87B78A630C0EFDF76C80CD24C997E252792E0317502AE1A02B9809F0D8685 +``` + +When querying a block by its height, use the `--type=height` flag: + +```shell +simd query block --type=height 1357 +``` + +When querying a block by its events, use the `--query` flag: + +```shell +simd query blocks --query 'message.sender=cosmos...' --page 1 --limit 30 +``` + +#### Transactions + +The `x/auth/tx` module provides a convinient CLI command for decoding and encoding transactions. + +#### `encode` + +The `encode` command encodes a transaction created with the `--generate-only` flag or signed with the sign command. +The transaction is seralized it to Protobuf and returned as base64. + +```bash +$ simd tx encode tx.json +Co8BCowBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEmwKLWNvc21vczFsNnZzcWhoN3Jud3N5cjJreXozampnM3FkdWF6OGd3Z3lsODI3NRItY29zbW9zMTU4c2FsZHlnOHBteHU3Znd2dDBkNng3amVzd3A0Z3d5a2xrNnkzGgwKBXN0YWtlEgMxMDASBhIEEMCaDA== +$ simd tx encode tx.signed.json +``` + +More information about the `encode` command can be found running `simd tx encode --help`. + +#### `decode` + +The `decode` commands decodes a transaction encoded with the `encode` command. + + +```bash +simd tx decode Co8BCowBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEmwKLWNvc21vczFsNnZzcWhoN3Jud3N5cjJreXozampnM3FkdWF6OGd3Z3lsODI3NRItY29zbW9zMTU4c2FsZHlnOHBteHU3Znd2dDBkNng3amVzd3A0Z3d5a2xrNnkzGgwKBXN0YWtlEgMxMDASBhIEEMCaDA== +``` + +More information about the `decode` command can be found running `simd tx decode --help`. + +### gRPC + +A user can query the `x/auth/tx` module using gRPC endpoints. + +#### `TxDecode` + +The `TxDecode` endpoint allows to decode a transaction. + +```shell +cosmos.tx.v1beta1.Service/TxDecode +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"tx_bytes":"Co8BCowBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEmwKLWNvc21vczFsNnZzcWhoN3Jud3N5cjJreXozampnM3FkdWF6OGd3Z3lsODI3NRItY29zbW9zMTU4c2FsZHlnOHBteHU3Znd2dDBkNng3amVzd3A0Z3d5a2xrNnkzGgwKBXN0YWtlEgMxMDASBhIEEMCaDA=="}' \ + localhost:9090 \ + cosmos.tx.v1beta1.Service/TxDecode +``` + +Example Output: + +```json +{ + "tx": { + "body": { + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"100"}],"fromAddress":"cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275","toAddress":"cosmos158saldyg8pmxu7fwvt0d6x7jeswp4gwyklk6y3"} + ] + }, + "authInfo": { + "fee": { + "gasLimit": "200000" + } + } + } +} +``` + +#### `TxEncode` + +The `TxEncode` endpoint allows to encode a transaction. + +```shell +cosmos.tx.v1beta1.Service/TxEncode +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"tx": { + "body": { + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"100"}],"fromAddress":"cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275","toAddress":"cosmos158saldyg8pmxu7fwvt0d6x7jeswp4gwyklk6y3"} + ] + }, + "authInfo": { + "fee": { + "gasLimit": "200000" + } + } + }}' \ + localhost:9090 \ + cosmos.tx.v1beta1.Service/TxEncode +``` + +Example Output: + +```json +{ + "txBytes": "Co8BCowBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEmwKLWNvc21vczFsNnZzcWhoN3Jud3N5cjJreXozampnM3FkdWF6OGd3Z3lsODI3NRItY29zbW9zMTU4c2FsZHlnOHBteHU3Znd2dDBkNng3amVzd3A0Z3d5a2xrNnkzGgwKBXN0YWtlEgMxMDASBhIEEMCaDA==" +} +``` + +#### `TxDecodeAmino` + +The `TxDecode` endpoint allows to decode an amino transaction. + +```shell +cosmos.tx.v1beta1.Service/TxDecodeAmino +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"amino_binary": "KCgWqQpvqKNhmgotY29zbW9zMXRzeno3cDJ6Z2Q3dnZrYWh5ZnJlNHduNXh5dTgwcnB0ZzZ2OWg1Ei1jb3Ntb3MxdHN6ejdwMnpnZDd2dmthaHlmcmU0d241eHl1ODBycHRnNnY5aDUaCwoFc3Rha2USAjEwEhEKCwoFc3Rha2USAjEwEMCaDCIGZm9vYmFy"}' \ + localhost:9090 \ + cosmos.tx.v1beta1.Service/TxDecodeAmino +``` + +Example Output: + +```json +{ + "aminoJson": "{\"type\":\"cosmos-sdk/StdTx\",\"value\":{\"msg\":[{\"type\":\"cosmos-sdk/MsgSend\",\"value\":{\"from_address\":\"cosmos1tszz7p2zgd7vvkahyfre4wn5xyu80rptg6v9h5\",\"to_address\":\"cosmos1tszz7p2zgd7vvkahyfre4wn5xyu80rptg6v9h5\",\"amount\":[{\"denom\":\"stake\",\"amount\":\"10\"}]}}],\"fee\":{\"amount\":[{\"denom\":\"stake\",\"amount\":\"10\"}],\"gas\":\"200000\"},\"signatures\":null,\"memo\":\"foobar\",\"timeout_height\":\"0\"}}" +} +``` + +#### `TxEncodeAmino` + +The `TxEncodeAmino` endpoint allows to encode an amino transaction. + +```shell +cosmos.tx.v1beta1.Service/TxEncodeAmino +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"amino_json":"{\"type\":\"cosmos-sdk/StdTx\",\"value\":{\"msg\":[{\"type\":\"cosmos-sdk/MsgSend\",\"value\":{\"from_address\":\"cosmos1tszz7p2zgd7vvkahyfre4wn5xyu80rptg6v9h5\",\"to_address\":\"cosmos1tszz7p2zgd7vvkahyfre4wn5xyu80rptg6v9h5\",\"amount\":[{\"denom\":\"stake\",\"amount\":\"10\"}]}}],\"fee\":{\"amount\":[{\"denom\":\"stake\",\"amount\":\"10\"}],\"gas\":\"200000\"},\"signatures\":null,\"memo\":\"foobar\",\"timeout_height\":\"0\"}}"}' \ + localhost:9090 \ + cosmos.tx.v1beta1.Service/TxEncodeAmino +``` + +Example Output: + +```json +{ + "amino_binary": "KCgWqQpvqKNhmgotY29zbW9zMXRzeno3cDJ6Z2Q3dnZrYWh5ZnJlNHduNXh5dTgwcnB0ZzZ2OWg1Ei1jb3Ntb3MxdHN6ejdwMnpnZDd2dmthaHlmcmU0d241eHl1ODBycHRnNnY5aDUaCwoFc3Rha2USAjEwEhEKCwoFc3Rha2USAjEwEMCaDCIGZm9vYmFy" +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/auth/README.md b/versioned_docs/version-0.47/integrate/modules/auth/README.md new file mode 100644 index 000000000..0c6364bf7 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/auth/README.md @@ -0,0 +1,705 @@ +--- +sidebar_position: 1 +--- + +# `x/auth` + +## Abstract + +This document specifies the auth module of the Cosmos SDK. + +The auth module is responsible for specifying the base transaction and account types +for an application, since the SDK itself is agnostic to these particulars. It contains +the middlewares, where all basic transaction validity checks (signatures, nonces, auxiliary fields) +are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts. + +This module is used in the Cosmos Hub. + +## Contents + +* [Concepts](#concepts) + * [Gas & Fees](#gas--fees) +* [State](#state) + * [Accounts](#accounts) +* [AnteHandlers](#antehandlers) +* [Keepers](#keepers) + * [Account Keeper](#account-keeper) +* [Parameters](#parameters) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) + +## Concepts + +**Note:** The auth module is different from the [authz module](../authz/README.md). + +The differences are: + +* `auth` - authentication of accounts and transactions for Cosmos SDK applications and is responsible for specifying the base transaction and account types. +* `authz` - authorization for accounts to perform actions on behalf of other accounts and enables a granter to grant authorizations to a grantee that allows the grantee to execute messages on behalf of the granter. + +### Gas & Fees + +Fees serve two purposes for an operator of the network. + +Fees limit the growth of the state stored by every full node and allow for +general purpose censorship of transactions of little economic value. Fees +are best suited as an anti-spam mechanism where validators are disinterested in +the use of the network and identities of users. + +Fees are determined by the gas limits and gas prices transactions provide, where +`fees = ceil(gasLimit * gasPrices)`. Txs incur gas costs for all state reads/writes, +signature verification, as well as costs proportional to the tx size. Operators +should set minimum gas prices when starting their nodes. They must set the unit +costs of gas in each token denomination they wish to support: + +`simd start ... --minimum-gas-prices=0.00001stake;0.05photinos` + +When adding transactions to mempool or gossipping transactions, validators check +if the transaction's gas prices, which are determined by the provided fees, meet +any of the validator's minimum gas prices. In other words, a transaction must +provide a fee of at least one denomination that matches a validator's minimum +gas price. + +CometBFT does not currently provide fee based mempool prioritization, and fee +based mempool filtering is local to node and not part of consensus. But with +minimum gas prices set, such a mechanism could be implemented by node operators. + +Because the market value for tokens will fluctuate, validators are expected to +dynamically adjust their minimum gas prices to a level that would encourage the +use of the network. + +## State + +### Accounts + +Accounts contain authentication information for a uniquely identified external user of an SDK blockchain, +including public key, address, and account number / sequence number for replay protection. For efficiency, +since account balances must also be fetched to pay fees, account structs also store the balance of a user +as `sdk.Coins`. + +Accounts are exposed externally as an interface, and stored internally as +either a base account or vesting account. Module clients wishing to add more +account types may do so. + +* `0x01 | Address -> ProtocolBuffer(account)` + +#### Account Interface + +The account interface exposes methods to read and write standard account information. +Note that all of these methods operate on an account struct conforming to the +interface - in order to write the account to the store, the account keeper will +need to be used. + +```go +// AccountI is an interface used to store coins at a given address within state. +// It presumes a notion of sequence numbers for replay protection, +// a notion of account numbers for replay protection for previously pruned accounts, +// and a pubkey for authentication purposes. +// +// Many complex conditions can be used in the concrete struct which implements AccountI. +type AccountI interface { + proto.Message + + GetAddress() sdk.AccAddress + SetAddress(sdk.AccAddress) error // errors if already set. + + GetPubKey() crypto.PubKey // can return nil. + SetPubKey(crypto.PubKey) error + + GetAccountNumber() uint64 + SetAccountNumber(uint64) error + + GetSequence() uint64 + SetSequence(uint64) error + + // Ensure that account implements stringer + String() string +} +``` + +##### Base Account + +A base account is the simplest and most common account type, which just stores all requisite +fields directly in a struct. + +```protobuf +// BaseAccount defines a base account type. It contains all the necessary fields +// for basic account functionality. Any custom account type should extend this +// type for additional functionality (e.g. vesting). +message BaseAccount { + string address = 1; + google.protobuf.Any pub_key = 2; + uint64 account_number = 3; + uint64 sequence = 4; +} +``` + +### Vesting Account + +See [Vesting](https://docs.cosmos.network/main/modules/auth/vesting/). + +## AnteHandlers + +The `x/auth` module presently has no transaction handlers of its own, but does expose the special `AnteHandler`, used for performing basic validity checks on a transaction, such that it could be thrown out of the mempool. +The `AnteHandler` can be seen as a set of decorators that check transactions within the current context, per [ADR 010](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-010-modular-antehandler.md). + +Note that the `AnteHandler` is called on both `CheckTx` and `DeliverTx`, as CometBFT proposers presently have the ability to include in their proposed block transactions which fail `CheckTx`. + +### Decorators + +The auth module provides `AnteDecorator`s that are recursively chained together into a single `AnteHandler` in the following order: + +* `SetUpContextDecorator`: Sets the `GasMeter` in the `Context` and wraps the next `AnteHandler` with a defer clause to recover from any downstream `OutOfGas` panics in the `AnteHandler` chain to return an error with information on gas provided and gas used. + +* `RejectExtensionOptionsDecorator`: Rejects all extension options which can optionally be included in protobuf transactions. + +* `MempoolFeeDecorator`: Checks if the `tx` fee is above local mempool `minFee` parameter during `CheckTx`. + +* `ValidateBasicDecorator`: Calls `tx.ValidateBasic` and returns any non-nil error. + +* `TxTimeoutHeightDecorator`: Check for a `tx` height timeout. + +* `ValidateMemoDecorator`: Validates `tx` memo with application parameters and returns any non-nil error. + +* `ConsumeGasTxSizeDecorator`: Consumes gas proportional to the `tx` size based on application parameters. + +* `DeductFeeDecorator`: Deducts the `FeeAmount` from first signer of the `tx`. If the `x/feegrant` module is enabled and a fee granter is set, it deducts fees from the fee granter account. + +* `SetPubKeyDecorator`: Sets the pubkey from a `tx`'s signers that does not already have its corresponding pubkey saved in the state machine and in the current context. + +* `ValidateSigCountDecorator`: Validates the number of signatures in `tx` based on app-parameters. + +* `SigGasConsumeDecorator`: Consumes parameter-defined amount of gas for each signature. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`. + +* `SigVerificationDecorator`: Verifies all signatures are valid. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`. + +* `IncrementSequenceDecorator`: Increments the account sequence for each signer to prevent replay attacks. + +## Keepers + +The auth module only exposes one keeper, the account keeper, which can be used to read and write accounts. + +### Account Keeper + +Presently only one fully-permissioned account keeper is exposed, which has the ability to both read and write +all fields of all accounts, and to iterate over all stored accounts. + +```go +// AccountKeeperI is the interface contract that x/auth's keeper implements. +type AccountKeeperI interface { + // Return a new account with the next account number and the specified address. Does not save the new account to the store. + NewAccountWithAddress(sdk.Context, sdk.AccAddress) types.AccountI + + // Return a new account with the next account number. Does not save the new account to the store. + NewAccount(sdk.Context, types.AccountI) types.AccountI + + // Check if an account exists in the store. + HasAccount(sdk.Context, sdk.AccAddress) bool + + // Retrieve an account from the store. + GetAccount(sdk.Context, sdk.AccAddress) types.AccountI + + // Set an account in the store. + SetAccount(sdk.Context, types.AccountI) + + // Remove an account from the store. + RemoveAccount(sdk.Context, types.AccountI) + + // Iterate over all accounts, calling the provided function. Stop iteration when it returns true. + IterateAccounts(sdk.Context, func(types.AccountI) bool) + + // Fetch the public key of an account at a specified address + GetPubKey(sdk.Context, sdk.AccAddress) (crypto.PubKey, error) + + // Fetch the sequence of an account at a specified address. + GetSequence(sdk.Context, sdk.AccAddress) (uint64, error) + + // Fetch the next account number, and increment the internal counter. + NextAccountNumber(sdk.Context) uint64 +} +``` + +## Parameters + +The auth module contains the following parameters: + +| Key | Type | Example | +| ---------------------- | --------------- | ------- | +| MaxMemoCharacters | uint64 | 256 | +| TxSigLimit | uint64 | 7 | +| TxSizeCostPerByte | uint64 | 10 | +| SigVerifyCostED25519 | uint64 | 590 | +| SigVerifyCostSecp256k1 | uint64 | 1000 | + +## Client + +### CLI + +A user can query and interact with the `auth` module using the CLI. + +### Query + +The `query` commands allow users to query `auth` state. + +```bash +simd query auth --help +``` + +#### account + +The `account` command allow users to query for an account by it's address. + +```bash +simd query auth account [address] [flags] +``` + +Example: + +```bash +simd query auth account cosmos1... +``` + +Example Output: + +```bash +'@type': /cosmos.auth.v1beta1.BaseAccount +account_number: "0" +address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2 +pub_key: + '@type': /cosmos.crypto.secp256k1.PubKey + key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD +sequence: "1" +``` + +#### accounts + +The `accounts` command allow users to query all the available accounts. + +```bash +simd query auth accounts [flags] +``` + +Example: + +```bash +simd query auth accounts +``` + +Example Output: + +```bash +accounts: +- '@type': /cosmos.auth.v1beta1.BaseAccount + account_number: "0" + address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2 + pub_key: + '@type': /cosmos.crypto.secp256k1.PubKey + key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD + sequence: "1" +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "8" + address: cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr + pub_key: null + sequence: "0" + name: transfer + permissions: + - minter + - burner +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "4" + address: cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh + pub_key: null + sequence: "0" + name: bonded_tokens_pool + permissions: + - burner + - staking +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "5" + address: cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r + pub_key: null + sequence: "0" + name: not_bonded_tokens_pool + permissions: + - burner + - staking +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "6" + address: cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn + pub_key: null + sequence: "0" + name: gov + permissions: + - burner +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "3" + address: cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl + pub_key: null + sequence: "0" + name: distribution + permissions: [] +- '@type': /cosmos.auth.v1beta1.BaseAccount + account_number: "1" + address: cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j + pub_key: null + sequence: "0" +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "7" + address: cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q + pub_key: null + sequence: "0" + name: mint + permissions: + - minter +- '@type': /cosmos.auth.v1beta1.ModuleAccount + base_account: + account_number: "2" + address: cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta + pub_key: null + sequence: "0" + name: fee_collector + permissions: [] +pagination: + next_key: null + total: "0" +``` + +#### params + +The `params` command allow users to query the current auth parameters. + +```bash +simd query auth params [flags] +``` + +Example: + +```bash +simd query auth params +``` + +Example Output: + +```bash +max_memo_characters: "256" +sig_verify_cost_ed25519: "590" +sig_verify_cost_secp256k1: "1000" +tx_sig_limit: "7" +tx_size_cost_per_byte: "10" +``` + +### Transactions + +The `auth` module supports transactions commands to help you with signing and more. Compared to other modules you can access directly the `auth` module transactions commands using the only `tx` command. + +Use directly the `--help` flag to get more information about the `tx` command. + +```bash +simd tx --help +``` + +#### `sign` + +The `sign` command allows users to sign transactions that was generated offline. + +```bash +simd tx sign tx.json --from $ALICE > tx.signed.json +``` + +The result is a signed transaction that can be broadcasted to the network thanks to the broadcast command. + +More information about the `sign` command can be found running `simd tx sign --help`. + +#### `sign-batch` + +The `sign-batch` command allows users to sign multiples offline generated transactions. +The transactions can be in one file, with one tx per line, or in multiple files. + +```bash +simd tx sign txs.json --from $ALICE > tx.signed.json +``` + +or + +```bash +simd tx sign tx1.json tx2.json tx3.json --from $ALICE > tx.signed.json +``` + +The result is multiples signed transactions. For combining the signed transactions into one transactions, use the `--append` flag. + +More information about the `sign-batch` command can be found running `simd tx sign-batch --help`. + +#### `multi-sign` + +The `multi-sign` command allows users to sign transactions that was generated offline by a multisig account. + +```bash +simd tx multisign transaction.json k1k2k3 k1sig.json k2sig.json k3sig.json +``` + +Where `k1k2k3` is the multisig account address, `k1sig.json` is the signature of the first signer, `k2sig.json` is the signature of the second signer, and `k3sig.json` is the signature of the third signer. + +More information about the `multi-sign` command can be found running `simd tx multi-sign --help`. + +#### `multisign-batch` + +The `multisign-batch` works the same way as `sign-batch`, but for multisig accounts. +With the difference that the `multisign-batch` command requires all transactions to be in one file, and the `--append` flag does not exist. + +More information about the `multisign-batch` command can be found running `simd tx multisign-batch --help`. + +#### `validate-signatures` + +The `validate-signatures` command allows users to validate the signatures of a signed transaction. + +```bash +$ simd tx validate-signatures tx.signed.json +Signers: + 0: cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275 + +Signatures: + 0: cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275 [OK] +``` + +More information about the `validate-signatures` command can be found running `simd tx validate-signatures --help`. + +#### `broadcast` + +The `broadcast` command allows users to broadcast a signed transaction to the network. + +```bash +simd tx broadcast tx.signed.json +``` + +More information about the `broadcast` command can be found running `simd tx broadcast --help`. + +#### `aux-to-fee` + +The `aux-to-fee` comamnds includes the aux signer data in the tx, broadcast the tx, and sends the tip amount to the broadcaster. +[Learn more about tip transaction](https://docs.cosmos.network/main/core/tips). + +```bash +# simd tx bank send --aux (optional: --tip --tipper ) +simd tx aux-to-fee tx.aux.signed.json +``` + +More information about the `aux-to-fee` command can be found running `simd tx aux-to-fee --help`. + +### gRPC + +A user can query the `auth` module using gRPC endpoints. + +#### Account + +The `account` endpoint allow users to query for an account by it's address. + +```bash +cosmos.auth.v1beta1.Query/Account +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"address":"cosmos1.."}' \ + localhost:9090 \ + cosmos.auth.v1beta1.Query/Account +``` + +Example Output: + +```bash +{ + "account":{ + "@type":"/cosmos.auth.v1beta1.BaseAccount", + "address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2", + "pubKey":{ + "@type":"/cosmos.crypto.secp256k1.PubKey", + "key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD" + }, + "sequence":"1" + } +} +``` + +#### Accounts + +The `accounts` endpoint allow users to query all the available accounts. + +```bash +cosmos.auth.v1beta1.Query/Accounts +``` + +Example: + +```bash +grpcurl -plaintext \ + localhost:9090 \ + cosmos.auth.v1beta1.Query/Accounts +``` + +Example Output: + +```bash +{ + "accounts":[ + { + "@type":"/cosmos.auth.v1beta1.BaseAccount", + "address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2", + "pubKey":{ + "@type":"/cosmos.crypto.secp256k1.PubKey", + "key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD" + }, + "sequence":"1" + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr", + "accountNumber":"8" + }, + "name":"transfer", + "permissions":[ + "minter", + "burner" + ] + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh", + "accountNumber":"4" + }, + "name":"bonded_tokens_pool", + "permissions":[ + "burner", + "staking" + ] + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r", + "accountNumber":"5" + }, + "name":"not_bonded_tokens_pool", + "permissions":[ + "burner", + "staking" + ] + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + "accountNumber":"6" + }, + "name":"gov", + "permissions":[ + "burner" + ] + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl", + "accountNumber":"3" + }, + "name":"distribution" + }, + { + "@type":"/cosmos.auth.v1beta1.BaseAccount", + "accountNumber":"1", + "address":"cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j" + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q", + "accountNumber":"7" + }, + "name":"mint", + "permissions":[ + "minter" + ] + }, + { + "@type":"/cosmos.auth.v1beta1.ModuleAccount", + "baseAccount":{ + "address":"cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta", + "accountNumber":"2" + }, + "name":"fee_collector" + } + ], + "pagination":{ + "total":"9" + } +} +``` + +#### Params + +The `params` endpoint allow users to query the current auth parameters. + +```bash +cosmos.auth.v1beta1.Query/Params +``` + +Example: + +```bash +grpcurl -plaintext \ + localhost:9090 \ + cosmos.auth.v1beta1.Query/Params +``` + +Example Output: + +```bash +{ + "params": { + "maxMemoCharacters": "256", + "txSigLimit": "7", + "txSizeCostPerByte": "10", + "sigVerifyCostEd25519": "590", + "sigVerifyCostSecp256k1": "1000" + } +} +``` + +### REST + +A user can query the `auth` module using REST endpoints. + +#### Account + +The `account` endpoint allow users to query for an account by it's address. + +```bash +/cosmos/auth/v1beta1/account?address={address} +``` + +#### Accounts + +The `accounts` endpoint allow users to query all the available accounts. + +```bash +/cosmos/auth/v1beta1/accounts +``` + +#### Params + +The `params` endpoint allow users to query the current auth parameters. + +```bash +/cosmos/auth/v1beta1/params +``` diff --git a/versioned_docs/version-0.47/integrate/modules/authz/README.md b/versioned_docs/version-0.47/integrate/modules/authz/README.md new file mode 100644 index 000000000..a641693df --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/authz/README.md @@ -0,0 +1,355 @@ +--- +sidebar_position: 1 +--- + +# `x/authz` + +## Abstract + +`x/authz` is an implementation of a Cosmos SDK module, per [ADR 30](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md), that allows +granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the `Authorization` interface. + +## Contents + +* [Concepts](#concepts) + * [Authorization and Grant](#authorization-and-grant) + * [Built-in Authorizations](#built-in-authorizations) + * [Gas](#gas) +* [State](#state) + * [Grant](#grant) + * [GrantQueue](#grantqueue) +* [Messages](#messages) + * [MsgGrant](#msggrant) + * [MsgRevoke](#msgrevoke) + * [MsgExec](#msgexec) +* [Events](#events) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) + +## Concepts + +### Authorization and Grant + +The `x/authz` module defines interfaces and messages grant authorizations to perform actions +on behalf of one account to other accounts. The design is defined in the [ADR 030](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md). + +A *grant* is an allowance to execute a Msg by the grantee on behalf of the granter. +Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. See the `SendAuthorization` example in the next section for more details. + +**Note:** The authz module is different from the [auth (authentication)](../auth/README.md) module that is responsible for specifying the base transaction and account types. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/authorizations.go#L11-L25 +``` + +### Built-in Authorizations + +The Cosmos SDK `x/authz` module comes with following authorization types: + +#### GenericAuthorization + +`GenericAuthorization` implements the `Authorization` interface that gives unrestricted permission to execute the provided Msg on behalf of granter's account. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L14-L22 +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/generic_authorization.go#L16-L29 +``` + +* `msg` stores Msg type URL. + +#### SendAuthorization + +`SendAuthorization` implements the `Authorization` interface for the `cosmos.bank.v1beta1.MsgSend` Msg. + +* It takes a (positive) `SpendLimit` that specifies the maximum amount of tokens the grantee can spend. The `SpendLimit` is updated as the tokens are spent. +* It takes an (optional) `AllowList` that specifies to which addresses a grantee can send token. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/authz.proto#L11-L30 +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/send_authorization.go#L29-L62 +``` + +* `spend_limit` keeps track of how many coins are left in the authorization. +* `allow_list` specifies an optional list of addresses to whom the grantee can send tokens on behalf of the granter. + +#### StakeAuthorization + +`StakeAuthorization` implements the `Authorization` interface for messages in the [staking module](../staking/README.md). It takes an `AuthorizationType` to specify whether you want to authorise delegating, undelegating or redelegating (i.e. these have to be authorised seperately). It also takes a required `MaxTokens` that keeps track of a limit to the amount of tokens that can be delegated/undelegated/redelegated. If left empty, the amount is unlimited. Additionally, this Msg takes an `AllowList` or a `DenyList`, which allows you to select which validators you allow or deny grantees to stake with. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/authz.proto#L11-L35 +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/types/authz.go#L15-L35 +``` + +### Gas + +In order to prevent DoS attacks, granting `StakeAuthorization`s with `x/authz` incurs gas. `StakeAuthorization` allows you to authorize another account to delegate, undelegate, or redelegate to validators. The authorizer can define a list of validators they allow or deny delegations to. The Cosmos SDK iterates over these lists and charge 10 gas for each validator in both of the lists. + +Since the state maintaining a list for granter, grantee pair with same expiration, we are iterating over the list to remove the grant (incase of any revoke of paritcular `msgType`) from the list and we are charging 20 gas per iteration. + +## State + +### Grant + +Grants are identified by combining granter address (the address bytes of the granter), grantee address (the address bytes of the grantee) and Authorization type (its type URL). Hence we only allow one grant for the (granter, grantee, Authorization) triple. + +* Grant: `0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes -> ProtocolBuffer(AuthorizationGrant)` + +The grant object encapsulates an `Authorization` type and an expiration timestamp: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L24-L32 +``` + +### GrantQueue + +We are maintaining a queue for authz pruning. Whenever a grant is created, an item will be added to `GrantQueue` with a key of expiration, granter, grantee. + +In `EndBlock` (which runs for every block) we continuously check and prune the expired grants by forming a prefix key with current blocktime that passed the stored expiration in `GrantQueue`, we iterate through all the matched records from `GrantQueue` and delete them from the `GrantQueue` & `Grant`s store. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/5f4ddc6f80f9707320eec42182184207fff3833a/x/authz/keeper/keeper.go#L378-L403 +``` + +* GrantQueue: `0x02 | expiration_bytes | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes -> ProtocalBuffer(GrantQueueItem)` + +The `expiration_bytes` are the expiration date in UTC with the format `"2006-01-02T15:04:05.000000000"`. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/keeper/keys.go#L77-L93 +``` + +The `GrantQueueItem` object contains the list of type urls between granter and grantee that expire at the time indicated in the key. + +## Messages + +In this section we describe the processing of messages for the authz module. + +### MsgGrant + +An authorization grant is created using the `MsgGrant` message. +If there is already a grant for the `(granter, grantee, Authorization)` triple, then the new grant overwrites the previous one. To update or extend an existing grant, a new grant with the same `(granter, grantee, Authorization)` triple should be created. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L35-L45 +``` + +The message handling should fail if: + +* both granter and grantee have the same address. +* provided `Expiration` time is less than current unix timestamp (but a grant will be created if no `expiration` time is provided since `expiration` is optional). +* provided `Grant.Authorization` is not implemented. +* `Authorization.MsgTypeURL()` is not defined in the router (there is no defined handler in the app router to handle that Msg types). + +### MsgRevoke + +A grant can be removed with the `MsgRevoke` message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L69-L78 +``` + +The message handling should fail if: + +* both granter and grantee have the same address. +* provided `MsgTypeUrl` is empty. + +NOTE: The `MsgExec` message removes a grant if the grant has expired. + +### MsgExec + +When a grantee wants to execute a transaction on behalf of a granter, they must send `MsgExec`. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L52-L63 +``` + +The message handling should fail if: + +* provided `Authorization` is not implemented. +* grantee doesn't have permission to run the transaction. +* if granted authorization is expired. + +## Events + +The authz module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main/cosmos.authz.v1beta1#cosmos.authz.v1beta1.EventGrant). + +## Client + +### CLI + +A user can query and interact with the `authz` module using the CLI. + +#### Query + +The `query` commands allow users to query `authz` state. + +```bash +simd query authz --help +``` + +##### grants + +The `grants` command allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type. + +```bash +simd query authz grants [granter-addr] [grantee-addr] [msg-type-url]? [flags] +``` + +Example: + +```bash +simd query authz grants cosmos1.. cosmos1.. /cosmos.bank.v1beta1.MsgSend +``` + +Example Output: + +```bash +grants: +- authorization: + '@type': /cosmos.bank.v1beta1.SendAuthorization + spend_limit: + - amount: "100" + denom: stake + expiration: "2022-01-01T00:00:00Z" +pagination: null +``` + +#### Transactions + +The `tx` commands allow users to interact with the `authz` module. + +```bash +simd tx authz --help +``` + +##### exec + +The `exec` command allows a grantee to execute a transaction on behalf of granter. + +```bash + simd tx authz exec [tx-json-file] --from [grantee] [flags] +``` + +Example: + +```bash +simd tx authz exec tx.json --from=cosmos1.. +``` + +##### grant + +The `grant` command allows a granter to grant an authorization to a grantee. + +```bash +simd tx authz grant --from [flags] +``` + +Example: + +```bash +simd tx authz grant cosmos1.. send --spend-limit=100stake --from=cosmos1.. +``` + +##### revoke + +The `revoke` command allows a granter to revoke an authorization from a grantee. + +```bash +simd tx authz revoke [grantee] [msg-type-url] --from=[granter] [flags] +``` + +Example: + +```bash +simd tx authz revoke cosmos1.. /cosmos.bank.v1beta1.MsgSend --from=cosmos1.. +``` + +### gRPC + +A user can query the `authz` module using gRPC endpoints. + +#### Grants + +The `Grants` endpoint allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type. + +```bash +cosmos.authz.v1beta1.Query/Grants +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"granter":"cosmos1..","grantee":"cosmos1..","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}' \ + localhost:9090 \ + cosmos.authz.v1beta1.Query/Grants +``` + +Example Output: + +```bash +{ + "grants": [ + { + "authorization": { + "@type": "/cosmos.bank.v1beta1.SendAuthorization", + "spendLimit": [ + { + "denom":"stake", + "amount":"100" + } + ] + }, + "expiration": "2022-01-01T00:00:00Z" + } + ] +} +``` + +### REST + +A user can query the `authz` module using REST endpoints. + +```bash +/cosmos/authz/v1beta1/grants +``` + +Example: + +```bash +curl "localhost:1317/cosmos/authz/v1beta1/grants?granter=cosmos1..&grantee=cosmos1..&msg_type_url=/cosmos.bank.v1beta1.MsgSend" +``` + +Example Output: + +```bash +{ + "grants": [ + { + "authorization": { + "@type": "/cosmos.bank.v1beta1.SendAuthorization", + "spend_limit": [ + { + "denom": "stake", + "amount": "100" + } + ] + }, + "expiration": "2022-01-01T00:00:00Z" + } + ], + "pagination": null +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/bank/README.md b/versioned_docs/version-0.47/integrate/modules/bank/README.md new file mode 100644 index 000000000..340822aa3 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/bank/README.md @@ -0,0 +1,950 @@ +--- +sidebar_position: 1 +--- + +# `x/bank` + +## Abstract + +This document specifies the bank module of the Cosmos SDK. + +The bank module is responsible for handling multi-asset coin transfers between +accounts and tracking special-case pseudo-transfers which must work differently +with particular kinds of accounts (notably delegating/undelegating for vesting +accounts). It exposes several interfaces with varying capabilities for secure +interaction with other modules which must alter user balances. + +In addition, the bank module tracks and provides query support for the total +supply of all assets used in the application. + +This module is used in the Cosmos Hub. + +## Contents + +* [Supply](#supply) + * [Total Supply](#total-supply) +* [Module Accounts](#module-accounts) + * [Permissions](#permissions) +* [State](#state) +* [Params](#params) +* [Keepers](#keepers) +* [Messages](#messages) +* [Events](#events) + * [Message Events](#message-events) + * [Keeper Events](#keeper-events) +* [Parameters](#parameters) + * [SendEnabled](#sendenabled) + * [DefaultSendEnabled](#defaultsendenabled) +* [Client](#client) + * [CLI](#cli) + * [Query](#query) + * [Transactions](#transactions) +* [gRPC](#grpc) + +## Supply + +The `supply` functionality: + +* passively tracks the total supply of coins within a chain, +* provides a pattern for modules to hold/interact with `Coins`, and +* introduces the invariant check to verify a chain's total supply. + +### Total Supply + +The total `Supply` of the network is equal to the sum of all coins from the +account. The total supply is updated every time a `Coin` is minted (eg: as part +of the inflation mechanism) or burned (eg: due to slashing or if a governance +proposal is vetoed). + +## Module Accounts + +The supply functionality introduces a new type of `auth.Account` which can be used by +modules to allocate tokens and in special cases mint or burn tokens. At a base +level these module accounts are capable of sending/receiving tokens to and from +`auth.Account`s and other module accounts. This design replaces previous +alternative designs where, to hold tokens, modules would burn the incoming +tokens from the sender account, and then track those tokens internally. Later, +in order to send tokens, the module would need to effectively mint tokens +within a destination account. The new design removes duplicate logic between +modules to perform this accounting. + +The `ModuleAccount` interface is defined as follows: + +```go +type ModuleAccount interface { + auth.Account // same methods as the Account interface + + GetName() string // name of the module; used to obtain the address + GetPermissions() []string // permissions of module account + HasPermission(string) bool +} +``` + +> **WARNING!** +> Any module or message handler that allows either direct or indirect sending of funds must explicitly guarantee those funds cannot be sent to module accounts (unless allowed). + +The supply `Keeper` also introduces new wrapper functions for the auth `Keeper` +and the bank `Keeper` that are related to `ModuleAccount`s in order to be able +to: + +* Get and set `ModuleAccount`s by providing the `Name`. +* Send coins from and to other `ModuleAccount`s or standard `Account`s + (`BaseAccount` or `VestingAccount`) by passing only the `Name`. +* `Mint` or `Burn` coins for a `ModuleAccount` (restricted to its permissions). + +### Permissions + +Each `ModuleAccount` has a different set of permissions that provide different +object capabilities to perform certain actions. Permissions need to be +registered upon the creation of the supply `Keeper` so that every time a +`ModuleAccount` calls the allowed functions, the `Keeper` can lookup the +permissions to that specific account and perform or not perform the action. + +The available permissions are: + +* `Minter`: allows for a module to mint a specific amount of coins. +* `Burner`: allows for a module to burn a specific amount of coins. +* `Staking`: allows for a module to delegate and undelegate a specific amount of coins. + +## State + +The `x/bank` module keeps state of the following primary objects: + +1. Account balances +2. Denomination metadata +3. The total supply of all balances +4. Information on which denominations are allowed to be sent. + +In addition, the `x/bank` module keeps the following indexes to manage the +aforementioned state: + +* Supply Index: `0x0 | byte(denom) -> byte(amount)` +* Denom Metadata Index: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)` +* Balances Index: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)` +* Reverse Denomination to Address Index: `0x03 | byte(denom) | 0x00 | []byte(address) -> 0` + +## Params + +The bank module stores it's params in state with the prefix of `0x05`, +it can be updated with governance or the address with authority. + +* Params: `0x05 | ProtocolBuffer(Params)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/bank.proto#L12-L23 +``` + +## Keepers + +The bank module provides these exported keeper interfaces that can be +passed to other modules that read or update account balances. Modules +should use the least-permissive interface that provides the functionality they +require. + +Best practices dictate careful review of `bank` module code to ensure that +permissions are limited in the way that you expect. + +### Denied Addresses + +The `x/bank` module accepts a map of addresses that are considered blocklisted +from directly and explicitly receiving funds through means such as `MsgSend` and +`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`. + +Typically, these addresses are module accounts. If these addresses receive funds +outside the expected rules of the state machine, invariants are likely to be +broken and could result in a halted network. + +By providing the `x/bank` module with a blocklisted set of addresses, an error occurs for the operation if a user or client attempts to directly or indirectly send funds to a blocklisted account, for example, by using [IBC](https://ibc.cosmos.network). + +### Common Types + +#### Input + +An input of a multiparty transfer + +```protobuf +// Input models transaction input. +message Input { + string address = 1; + repeated cosmos.base.v1beta1.Coin coins = 2; +} +``` + +#### Output + +An output of a multiparty transfer. + +```protobuf +// Output models transaction outputs. +message Output { + string address = 1; + repeated cosmos.base.v1beta1.Coin coins = 2; +} +``` + +### BaseKeeper + +The base keeper provides full-permission access: the ability to arbitrary modify any account's balance and mint or burn coins. + +Restricted permission to mint per module could be achieved by using baseKeeper with `WithMintCoinsRestriction` to give specific restrictions to mint (e.g. only minting certain denom). + +```go +// Keeper defines a module interface that facilitates the transfer of coins +// between accounts. +type Keeper interface { + SendKeeper + WithMintCoinsRestriction(MintingRestrictionFn) BaseKeeper + + InitGenesis(context.Context, *types.GenesisState) + ExportGenesis(context.Context) *types.GenesisState + + GetSupply(ctx context.Context, denom string) sdk.Coin + HasSupply(ctx context.Context, denom string) bool + GetPaginatedTotalSupply(ctx context.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) + IterateTotalSupply(ctx context.Context, cb func(sdk.Coin) bool) + GetDenomMetaData(ctx context.Context, denom string) (types.Metadata, bool) + HasDenomMetaData(ctx context.Context, denom string) bool + SetDenomMetaData(ctx context.Context, denomMetaData types.Metadata) + IterateAllDenomMetaData(ctx context.Context, cb func(types.Metadata) bool) + + SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + DelegateCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + UndelegateCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + + DelegateCoins(ctx context.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error + UndelegateCoins(ctx context.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error + + // GetAuthority gets the address capable of executing governance proposal messages. Usually the gov module account. + GetAuthority() string + + types.QueryServer +} +``` + +### SendKeeper + +The send keeper provides access to account balances and the ability to transfer coins between +accounts. The send keeper does not alter the total supply (mint or burn coins). + +```go +// SendKeeper defines a module interface that facilitates the transfer of coins +// between accounts without the possibility of creating coins. +type SendKeeper interface { + ViewKeeper + + InputOutputCoins(ctx context.Context, inputs types.Input, outputs []types.Output) error + SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + + GetParams(ctx context.Context) types.Params + SetParams(ctx context.Context, params types.Params) error + + IsSendEnabledDenom(ctx context.Context, denom string) bool + SetSendEnabled(ctx context.Context, denom string, value bool) + SetAllSendEnabled(ctx context.Context, sendEnableds []*types.SendEnabled) + DeleteSendEnabled(ctx context.Context, denom string) + IterateSendEnabledEntries(ctx context.Context, cb func(denom string, sendEnabled bool) (stop bool)) + GetAllSendEnabledEntries(ctx context.Context) []types.SendEnabled + + IsSendEnabledCoin(ctx context.Context, coin sdk.Coin) bool + IsSendEnabledCoins(ctx context.Context, coins ...sdk.Coin) error + + BlockedAddr(addr sdk.AccAddress) bool +} +``` + +### ViewKeeper + +The view keeper provides read-only access to account balances. The view keeper does not have balance alteration functionality. All balance lookups are `O(1)`. + +```go +// ViewKeeper defines a module interface that facilitates read only access to +// account balances. +type ViewKeeper interface { + ValidateBalance(ctx context.Context, addr sdk.AccAddress) error + HasBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) bool + + GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins + GetAccountsBalances(ctx context.Context) []types.Balance + GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin + LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins + SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins + SpendableCoin(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin + + IterateAccountBalances(ctx context.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool)) + IterateAllBalances(ctx context.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool)) +} +``` + +## Messages + +### MsgSend + +Send coins from one address to another. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L38-L53 +``` + +The message will fail under the following conditions: + +* The coins do not have sending enabled +* The `to` address is restricted + +### MsgMultiSend + +Send coins from one sender and to a series of different address. If any of the receiving addresses do not correspond to an existing account, a new account is created. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L58-L69 +``` + +The message will fail under the following conditions: + +* Any of the coins do not have sending enabled +* Any of the `to` addresses are restricted +* Any of the coins are locked +* The inputs and outputs do not correctly correspond to one another + +### MsgUpdateParams + +The `bank` module params can be updated through `MsgUpdateParams`, which can be done using governance proposal. The signer will always be the `gov` module account address. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L74-L88 +``` + +The message handling can fail if: + +* signer is not the gov module account address. + +### MsgSetSendEnabled + +Used with the x/gov module to set create/edit SendEnabled entries. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L96-L117 +``` + +The message will fail under the following conditions: + +* The authority is not a bech32 address. +* The authority is not x/gov module's address. +* There are multiple SendEnabled entries with the same Denom. +* One or more SendEnabled entries has an invalid Denom. + +## Events + +The bank module emits the following events: + +### Message Events + +#### MsgSend + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| transfer | recipient | {recipientAddress} | +| transfer | amount | {amount} | +| message | module | bank | +| message | action | send | +| message | sender | {senderAddress} | + +#### MsgMultiSend + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| transfer | recipient | {recipientAddress} | +| transfer | amount | {amount} | +| message | module | bank | +| message | action | multisend | +| message | sender | {senderAddress} | + +### Keeper Events + +In addition to message events, the bank keeper will produce events when the following methods are called (or any method which ends up calling them) + +#### MintCoins + +```json +{ + "type": "coinbase", + "attributes": [ + { + "key": "minter", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being minted}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +#### BurnCoins + +```json +{ + "type": "burn", + "attributes": [ + { + "key": "burner", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +#### addCoins + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the address beneficiary of the coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +#### subUnlockedCoins/DelegateCoins + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the address which is spending coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being spent}}", + "index": true + } + ] +} +``` + +## Parameters + +The bank module contains the following parameters + +### SendEnabled + +The SendEnabled parameter is now deprecated and not to be use. It is replaced +with state store records. + + +### DefaultSendEnabled + +The default send enabled value controls send transfer capability for all +coin denominations unless specifically included in the array of `SendEnabled` +parameters. + +## Client + +### CLI + +A user can query and interact with the `bank` module using the CLI. + +#### Query + +The `query` commands allow users to query `bank` state. + +```shell +simd query bank --help +``` + +##### balances + +The `balances` command allows users to query account balances by address. + +```shell +simd query bank balances [address] [flags] +``` + +Example: + +```shell +simd query bank balances cosmos1.. +``` + +Example Output: + +```yml +balances: +- amount: "1000000000" + denom: stake +pagination: + next_key: null + total: "0" +``` + +##### denom-metadata + +The `denom-metadata` command allows users to query metadata for coin denominations. A user can query metadata for a single denomination using the `--denom` flag or all denominations without it. + +```shell +simd query bank denom-metadata [flags] +``` + +Example: + +```shell +simd query bank denom-metadata --denom stake +``` + +Example Output: + +```yml +metadata: + base: stake + denom_units: + - aliases: + - STAKE + denom: stake + description: native staking token of simulation app + display: stake + name: SimApp Token + symbol: STK +``` + +##### total + +The `total` command allows users to query the total supply of coins. A user can query the total supply for a single coin using the `--denom` flag or all coins without it. + +```shell +simd query bank total [flags] +``` + +Example: + +```shell +simd query bank total --denom stake +``` + +Example Output: + +```yml +amount: "10000000000" +denom: stake +``` + +##### send-enabled + +The `send-enabled` command allows users to query for all or some SendEnabled entries. + +```shell +simd query bank send-enabled [denom1 ...] [flags] +``` + +Example: + +```shell +simd query bank send-enabled +``` + +Example output: + +```yml +send_enabled: +- denom: foocoin + enabled: true +- denom: barcoin +pagination: + next-key: null + total: 2 +``` + +#### Transactions + +The `tx` commands allow users to interact with the `bank` module. + +```shell +simd tx bank --help +``` + +##### send + +The `send` command allows users to send funds from one account to another. + +```shell +simd tx bank send [from_key_or_address] [to_address] [amount] [flags] +``` + +Example: + +```shell +simd tx bank send cosmos1.. cosmos1.. 100stake +``` + +## gRPC + +A user can query the `bank` module using gRPC endpoints. + +### Balance + +The `Balance` endpoint allows users to query account balance by address for a given denomination. + +```shell +cosmos.bank.v1beta1.Query/Balance +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"address":"cosmos1..","denom":"stake"}' \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/Balance +``` + +Example Output: + +```json +{ + "balance": { + "denom": "stake", + "amount": "1000000000" + } +} +``` + +### AllBalances + +The `AllBalances` endpoint allows users to query account balance by address for all denominations. + +```shell +cosmos.bank.v1beta1.Query/AllBalances +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"address":"cosmos1.."}' \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/AllBalances +``` + +Example Output: + +```json +{ + "balances": [ + { + "denom": "stake", + "amount": "1000000000" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### DenomMetadata + +The `DenomMetadata` endpoint allows users to query metadata for a single coin denomination. + +```shell +cosmos.bank.v1beta1.Query/DenomMetadata +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"denom":"stake"}' \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/DenomMetadata +``` + +Example Output: + +```json +{ + "metadata": { + "description": "native staking token of simulation app", + "denomUnits": [ + { + "denom": "stake", + "aliases": [ + "STAKE" + ] + } + ], + "base": "stake", + "display": "stake", + "name": "SimApp Token", + "symbol": "STK" + } +} +``` + +### DenomsMetadata + +The `DenomsMetadata` endpoint allows users to query metadata for all coin denominations. + +```shell +cosmos.bank.v1beta1.Query/DenomsMetadata +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/DenomsMetadata +``` + +Example Output: + +```json +{ + "metadatas": [ + { + "description": "native staking token of simulation app", + "denomUnits": [ + { + "denom": "stake", + "aliases": [ + "STAKE" + ] + } + ], + "base": "stake", + "display": "stake", + "name": "SimApp Token", + "symbol": "STK" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### DenomOwners + +The `DenomOwners` endpoint allows users to query metadata for a single coin denomination. + +```shell +cosmos.bank.v1beta1.Query/DenomOwners +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"denom":"stake"}' \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/DenomOwners +``` + +Example Output: + +```json +{ + "denomOwners": [ + { + "address": "cosmos1..", + "balance": { + "denom": "stake", + "amount": "5000000000" + } + }, + { + "address": "cosmos1..", + "balance": { + "denom": "stake", + "amount": "5000000000" + } + }, + ], + "pagination": { + "total": "2" + } +} +``` + +### TotalSupply + +The `TotalSupply` endpoint allows users to query the total supply of all coins. + +```shell +cosmos.bank.v1beta1.Query/TotalSupply +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/TotalSupply +``` + +Example Output: + +```json +{ + "supply": [ + { + "denom": "stake", + "amount": "10000000000" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### SupplyOf + +The `SupplyOf` endpoint allows users to query the total supply of a single coin. + +```shell +cosmos.bank.v1beta1.Query/SupplyOf +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"denom":"stake"}' \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/SupplyOf +``` + +Example Output: + +```json +{ + "amount": { + "denom": "stake", + "amount": "10000000000" + } +} +``` + +### Params + +The `Params` endpoint allows users to query the parameters of the `bank` module. + +```shell +cosmos.bank.v1beta1.Query/Params +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/Params +``` + +Example Output: + +```json +{ + "params": { + "defaultSendEnabled": true + } +} +``` + +### SendEnabled + +The `SendEnabled` enpoints allows users to query the SendEnabled entries of the `bank` module. + +Any denominations NOT returned, use the `Params.DefaultSendEnabled` value. + +```shell +cosmos.bank.v1beta1.Query/SendEnabled +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/SendEnabled +``` + +Example Output: + +```json +{ + "send_enabled": [ + { + "denom": "foocoin", + "enabled": true + }, + { + "denom": "barcoin" + } + ], + "pagination": { + "next-key": null, + "total": 2 + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/circuit/README.md b/versioned_docs/version-0.47/integrate/modules/circuit/README.md new file mode 100644 index 000000000..332ebf214 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/circuit/README.md @@ -0,0 +1,115 @@ +# `x/circuit` + +## Concepts + +Circuit Breaker is a module that is meant to avoid a chain needing to halt/shut down in the presence of a vulnerability, instead the module will allow specific messages or all messages to be disabled. When operating a chain, if it is app specific then a halt of the chain is less detrimental, but if there are applications built on top of the chain then halting is expensive due to the disturbance to applications. + +Circuit Breaker works with the idea that an address or set of addresses have the right to block messages from being executed and/or included in the mempool. Any address with a permission is able to reset the circuit breaker for the message. + +## State + +### Accounts + +* AccountPermissions `0x1 | account_address -> ProtocolBuffer(CircuitBreakerPermissions)` + +```go +type level int32 + +const ( + // LEVEL_NONE_UNSPECIFIED indicates that the account will have no circuit + // breaker permissions. + LEVEL_NONE_UNSPECIFIED = iota + // LEVEL_SOME_MSGS indicates that the account will have permission to + // trip or reset the circuit breaker for some Msg type URLs. If this level + // is chosen, a non-empty list of Msg type URLs must be provided in + // limit_type_urls. + LEVEL_SOME_MSGS + // LEVEL_ALL_MSGS indicates that the account can trip or reset the circuit + // breaker for Msg's of all type URLs. + LEVEL_ALL_MSGS + // LEVEL_SUPER_ADMIN indicates that the account can take all circuit breaker + // actions and can grant permissions to other accounts. + LEVEL_SUPER_ADMIN +) + +type Access struct { + level int32 + msgs []string // if full permission, msgs can be empty +} +``` + + +### Disable List + +List of type urls that are disabled. + +* DisableList `0x2 | msg_type_url -> []byte{}` + +## State Transitions + +### Authorize + +Authorize, is called by the module authority (default governance module account) or any account with `LEVEL_SUPER_ADMIN` to give permission to disable/enable messages to another account. There are three levels of permissions that can be granted. `LEVEL_SOME_MSGS` limits the number of messages that can be disabled. `LEVEL_ALL_MSGS` permits all messages to be disabled. `LEVEL_SUPER_ADMIN` allows an account to take all circuit breaker actions including authorizing and deauthorizing other accounts. + +```protobuf + // AuthorizeCircuitBreaker allows a super-admin to grant (or revoke) another + // account's circuit breaker permissions. + rpc AuthorizeCircuitBreaker(MsgAuthorizeCircuitBreaker) returns (MsgAuthorizeCircuitBreakerResponse); +``` + +### Trip + +Trip, is called by an account to disable message execution for a specific msgURL. + +```protobuf + // TripCircuitBreaker pauses processing of Msg's in the state machine. + rpc TripCircuitBreaker(MsgTripCircuitBreaker) returns (MsgTripCircuitBreakerResponse); +``` + +### Reset + +Reset is called to enable execution of a previously disabled message. + +```protobuf + // ResetCircuitBreaker resumes processing of Msg's in the state machine that + // have been been paused using TripCircuitBreaker. + rpc ResetCircuitBreaker(MsgResetCircuitBreaker) returns (MsgResetCircuitBreakerResponse); +``` + +## Messages + +### MsgAuthorizeCircuitBreaker + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/circuit/v1/tx.proto#L25-L75 +``` + +This message is expected to fail if: + +* the granter is not an account with permission level `LEVEL_SUPER_ADMIN` or the module authority +* if the type urls does not exist + +### MsgTripCircuitBreaker + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/circuit/v1/tx.proto#L77-L93 +``` + +This message is expected to fail if: + +* if the signer does not have a permission level with the ability to disable the specified type url message +* if the type urls does not exist + +### MsgResetCircuitBreaker + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/circuit/v1/tx.proto#L95-109 +``` + +This message is expected to fail if: + +* if the type urls does not exist +* if the type url is not disabled + +* `## Events` - list and describe event tags used +* `## Client` - list and describe CLI commands and gRPC and REST endpoints diff --git a/versioned_docs/version-0.47/integrate/modules/consensus/README.md b/versioned_docs/version-0.47/integrate/modules/consensus/README.md new file mode 100644 index 000000000..902280a6e --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/consensus/README.md @@ -0,0 +1,7 @@ +--- +sidebar_position: 1 +--- + +# `x/consensus` + +Functionality to modify CometBFT's ABCI consensus params. diff --git a/versioned_docs/version-0.47/integrate/modules/crisis/README.md b/versioned_docs/version-0.47/integrate/modules/crisis/README.md new file mode 100644 index 000000000..e4e29d0a1 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/crisis/README.md @@ -0,0 +1,110 @@ +--- +sidebar_position: 1 +--- + +# `x/crisis` + +## Overview + +The crisis module halts the blockchain under the circumstance that a blockchain +invariant is broken. Invariants can be registered with the application during the +application initialization process. + +## Contents + +* [State](#state) +* [Messages](#messages) +* [Events](#events) +* [Parameters](#parameters) +* [Client](#client) + * [CLI](#cli) + +## State + +### ConstantFee + +Due to the anticipated large gas cost requirement to verify an invariant (and +potential to exceed the maximum allowable block gas limit) a constant fee is +used instead of the standard gas consumption method. The constant fee is +intended to be larger than the anticipated gas cost of running the invariant +with the standard gas consumption method. + +The ConstantFee param is stored in the module params state with the prefix of `0x01`, +it can be updated with governance or the address with authority. + +* Params: `mint/params -> legacy_amino(sdk.Coin)` + +## Messages + +In this section we describe the processing of the crisis messages and the +corresponding updates to the state. + +### MsgVerifyInvariant + +Blockchain invariants can be checked using the `MsgVerifyInvariant` message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/crisis/v1beta1/tx.proto#L26-L42 +``` + +This message is expected to fail if: + +* the sender does not have enough coins for the constant fee +* the invariant route is not registered + +This message checks the invariant provided, and if the invariant is broken it +panics, halting the blockchain. If the invariant is broken, the constant fee is +never deducted as the transaction is never committed to a block (equivalent to +being refunded). However, if the invariant is not broken, the constant fee will +not be refunded. + +## Events + +The crisis module emits the following events: + +### Handlers + +#### MsgVerifyInvariance + +| Type | Attribute Key | Attribute Value | +|-----------|---------------|------------------| +| invariant | route | {invariantRoute} | +| message | module | crisis | +| message | action | verify_invariant | +| message | sender | {senderAddress} | + +## Parameters + +The crisis module contains the following parameters: + +| Key | Type | Example | +|-------------|---------------|-----------------------------------| +| ConstantFee | object (coin) | {"denom":"uatom","amount":"1000"} | + +## Client + +### CLI + +A user can query and interact with the `crisis` module using the CLI. + +#### Transactions + +The `tx` commands allow users to interact with the `crisis` module. + +```bash +simd tx crisis --help +``` + +##### invariant-broken + +The `invariant-broken` command submits proof when an invariant was broken to halt the chain + +```bash +simd tx crisis invariant-broken [module-name] [invariant-route] [flags] +``` + +Example: + +```bash +simd tx crisis invariant-broken bank total-supply --from=[keyname or address] +``` diff --git a/versioned_docs/version-0.47/integrate/modules/distribution/README.md b/versioned_docs/version-0.47/integrate/modules/distribution/README.md new file mode 100644 index 000000000..e46dab3fc --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/distribution/README.md @@ -0,0 +1,1042 @@ +--- +sidebar_position: 1 +--- + +# `x/distribution` + +## Overview + +This _simple_ distribution mechanism describes a functional way to passively +distribute rewards between validators and delegators. Note that this mechanism does +not distribute funds in as precisely as active reward distribution mechanisms and +will therefore be upgraded in the future. + +The mechanism operates as follows. Collected rewards are pooled globally and +divided out passively to validators and delegators. Each validator has the +opportunity to charge commission to the delegators on the rewards collected on +behalf of the delegators. Fees are collected directly into a global reward pool +and validator proposer-reward pool. Due to the nature of passive accounting, +whenever changes to parameters which affect the rate of reward distribution +occurs, withdrawal of rewards must also occur. + +* Whenever withdrawing, one must withdraw the maximum amount they are entitled + to, leaving nothing in the pool. +* Whenever bonding, unbonding, or re-delegating tokens to an existing account, a + full withdrawal of the rewards must occur (as the rules for lazy accounting + change). +* Whenever a validator chooses to change the commission on rewards, all accumulated + commission rewards must be simultaneously withdrawn. + +The above scenarios are covered in `hooks.md`. + +The distribution mechanism outlined herein is used to lazily distribute the +following rewards between validators and associated delegators: + +* multi-token fees to be socially distributed +* inflated staked asset provisions +* validator commission on all rewards earned by their delegators stake + +Fees are pooled within a global pool. The mechanisms used allow for validators +and delegators to independently and lazily withdraw their rewards. + +## Shortcomings + +As a part of the lazy computations, each delegator holds an accumulation term +specific to each validator which is used to estimate what their approximate +fair portion of tokens held in the global fee pool is owed to them. + +```text +entitlement = delegator-accumulation / all-delegators-accumulation +``` + +Under the circumstance that there was constant and equal flow of incoming +reward tokens every block, this distribution mechanism would be equal to the +active distribution (distribute individually to all delegators each block). +However, this is unrealistic so deviations from the active distribution will +occur based on fluctuations of incoming reward tokens as well as timing of +reward withdrawal by other delegators. + +If you happen to know that incoming rewards are about to significantly increase, +you are incentivized to not withdraw until after this event, increasing the +worth of your existing _accum_. See [#2764](https://github.com/cosmos/cosmos-sdk/issues/2764) +for further details. + +## Effect on Staking + +Charging commission on Atom provisions while also allowing for Atom-provisions +to be auto-bonded (distributed directly to the validators bonded stake) is +problematic within BPoS. Fundamentally, these two mechanisms are mutually +exclusive. If both commission and auto-bonding mechanisms are simultaneously +applied to the staking-token then the distribution of staking-tokens between +any validator and its delegators will change with each block. This then +necessitates a calculation for each delegation records for each block - +which is considered computationally expensive. + +In conclusion, we can only have Atom commission and unbonded atoms +provisions or bonded atom provisions with no Atom commission, and we elect to +implement the former. Stakeholders wishing to rebond their provisions may elect +to set up a script to periodically withdraw and rebond rewards. + +## Contents + +* [Concepts](#concepts) +* [State](#state) + * [FeePool](#feepool) + * [Validator Distribution](#validator-distribution) + * [Delegation Distribution](#delegation-distribution) + * [Params](#params) +* [Begin Block](#begin-block) +* [Messages](#messages) +* [Hooks](#hooks) +* [Events](#events) +* [Parameters](#parameters) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + +## Concepts + +In Proof of Stake (PoS) blockchains, rewards gained from transaction fees are paid to validators. The fee distribution module fairly distributes the rewards to the validators' constituent delegators. + +Rewards are calculated per period. The period is updated each time a validator's delegation changes, for example, when the validator receives a new delegation. +The rewards for a single validator can then be calculated by taking the total rewards for the period before the delegation started, minus the current total rewards. +To learn more, see the [F1 Fee Distribution paper](https://github.com/cosmos/cosmos-sdk/tree/main/docs/spec/fee_distribution/f1_fee_distr.pdf). + +The commission to the validator is paid when the validator is removed or when the validator requests a withdrawal. +The commission is calculated and incremented at every `BeginBlock` operation to update accumulated fee amounts. + +The rewards to a delegator are distributed when the delegation is changed or removed, or a withdrawal is requested. +Before rewards are distributed, all slashes to the validator that occurred during the current delegation are applied. + +### Reference Counting in F1 Fee Distribution + +In F1 fee distribution, the rewards a delegator receives are calculated when their delegation is withdrawn. This calculation must read the terms of the summation of rewards divided by the share of tokens from the period which they ended when they delegated, and the final period that was created for the withdrawal. + +Additionally, as slashes change the amount of tokens a delegation will have (but we calculate this lazily, +only when a delegator un-delegates), we must calculate rewards in separate periods before / after any slashes +which occurred in between when a delegator delegated and when they withdrew their rewards. Thus slashes, like +delegations, reference the period which was ended by the slash event. + +All stored historical rewards records for periods which are no longer referenced by any delegations +or any slashes can thus be safely removed, as they will never be read (future delegations and future +slashes will always reference future periods). This is implemented by tracking a `ReferenceCount` +along with each historical reward storage entry. Each time a new object (delegation or slash) +is created which might need to reference the historical record, the reference count is incremented. +Each time one object which previously needed to reference the historical record is deleted, the reference +count is decremented. If the reference count hits zero, the historical record is deleted. + +## State + +### FeePool + +All globally tracked parameters for distribution are stored within +`FeePool`. Rewards are collected and added to the reward pool and +distributed to validators/delegators from here. + +Note that the reward pool holds decimal coins (`DecCoins`) to allow +for fractions of coins to be received from operations like inflation. +When coins are distributed from the pool they are truncated back to +`sdk.Coins` which are non-decimal. + +* FeePool: `0x00 -> ProtocolBuffer(FeePool)` + +```go +// coins with decimal +type DecCoins []DecCoin + +type DecCoin struct { + Amount math.LegacyDec + Denom string +} +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/distribution.proto#L116-L123 +``` + +### Validator Distribution + +Validator distribution information for the relevant validator is updated each time: + +1. delegation amount to a validator is updated, +2. any delegator withdraws from a validator, or +3. the validator withdraws its commission. + +* ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` + +```go +type ValidatorDistInfo struct { + OperatorAddress sdk.AccAddress + SelfBondRewards sdkmath.DecCoins + ValidatorCommission types.ValidatorAccumulatedCommission +} +``` + +### Delegation Distribution + +Each delegation distribution only needs to record the height at which it last +withdrew fees. Because a delegation must withdraw fees each time it's +properties change (aka bonded tokens etc.) its properties will remain constant +and the delegator's _accumulation_ factor can be calculated passively knowing +only the height of the last withdrawal and its current properties. + +* DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)` + +```go +type DelegationDistInfo struct { + WithdrawalHeight int64 // last time this delegation withdrew rewards +} +``` + +### Params + +The distribution module stores it's params in state with the prefix of `0x09`, +it can be updated with governance or the address with authority. + +* Params: `0x09 | ProtocolBuffer(Params)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/distribution.proto#L12-L42 +``` + +## Begin Block + +At each `BeginBlock`, all fees received in the previous block are transferred to +the distribution `ModuleAccount` account. When a delegator or validator +withdraws their rewards, they are taken out of the `ModuleAccount`. During begin +block, the different claims on the fees collected are updated as follows: + +* The reserve community tax is charged. +* The remainder is distributed proportionally by voting power to all bonded validators + +### The Distribution Scheme + +See [params](#params) for description of parameters. + +Let `fees` be the total fees collected in the previous block, including +inflationary rewards to the stake. All fees are collected in a specific module +account during the block. During `BeginBlock`, they are sent to the +`"distribution"` `ModuleAccount`. No other sending of tokens occurs. Instead, the +rewards each account is entitled to are stored, and withdrawals can be triggered +through the messages `FundCommunityPool`, `WithdrawValidatorCommission` and +`WithdrawDelegatorReward`. + +#### Reward to the Community Pool + +The community pool gets `community_tax * fees`, plus any remaining dust after +validators get their rewards that are always rounded down to the nearest +integer value. + +#### Reward To the Validators + +The proposer receives no extra rewards. All fees are distributed among all the +bonded validators, including the proposer, in proportion to their consensus power. + +```text +powFrac = validator power / total bonded validator power +voteMul = 1 - community_tax +``` + +All validators receive `fees * voteMul * powFrac`. + +#### Rewards to Delegators + +Each validator's rewards are distributed to its delegators. The validator also +has a self-delegation that is treated like a regular delegation in +distribution calculations. + +The validator sets a commission rate. The commission rate is flexible, but each +validator sets a maximum rate and a maximum daily increase. These maximums cannot be exceeded and protect delegators from sudden increases of validator commission rates to prevent validators from taking all of the rewards. + +The outstanding rewards that the operator is entitled to are stored in +`ValidatorAccumulatedCommission`, while the rewards the delegators are entitled +to are stored in `ValidatorCurrentRewards`. The [F1 fee distribution scheme](#concepts) is used to calculate the rewards per delegator as they +withdraw or update their delegation, and is thus not handled in `BeginBlock`. + +#### Example Distribution + +For this example distribution, the underlying consensus engine selects block proposers in +proportion to their power relative to the entire bonded power. + +All validators are equally performant at including pre-commits in their proposed +blocks. Then hold `(pre_commits included) / (total bonded validator power)` +constant so that the amortized block reward for the validator is `( validator power / total bonded power) * (1 - community tax rate)` of +the total rewards. Consequently, the reward for a single delegator is: + +```text +(delegator proportion of the validator power / validator power) * (validator power / total bonded power) + * (1 - community tax rate) * (1 - validator commission rate) += (delegator proportion of the validator power / total bonded power) * (1 - +community tax rate) * (1 - validator commission rate) +``` + +## Messages + +### MsgSetWithdrawAddress + +By default, the withdraw address is the delegator address. To change its withdraw address, a delegator must send a `MsgSetWithdrawAddress` message. +Changing the withdraw address is possible only if the parameter `WithdrawAddrEnabled` is set to `true`. + +The withdraw address cannot be any of the module accounts. These accounts are blocked from being withdraw addresses by being added to the distribution keeper's `blockedAddrs` array at initialization. + +Response: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L49-L60 +``` + +```go +func (k Keeper) SetWithdrawAddr(ctx context.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error + if k.blockedAddrs[withdrawAddr.String()] { + fail with "`{withdrawAddr}` is not allowed to receive external funds" + } + + if !k.GetWithdrawAddrEnabled(ctx) { + fail with `ErrSetWithdrawAddrDisabled` + } + + k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr) +``` + +### MsgWithdrawDelegatorReward + +A delegator can withdraw its rewards. +Internally in the distribution module, this transaction simultaneously removes the previous delegation with associated rewards, the same as if the delegator simply started a new delegation of the same value. +The rewards are sent immediately from the distribution `ModuleAccount` to the withdraw address. +Any remainder (truncated decimals) are sent to the community pool. +The starting height of the delegation is set to the current validator period, and the reference count for the previous period is decremented. +The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator. + +In the F1 distribution, the total rewards are calculated per validator period, and a delegator receives a piece of those rewards in proportion to their stake in the validator. +In basic F1, the total rewards that all the delegators are entitled to between to periods is calculated the following way. +Let `R(X)` be the total accumulated rewards up to period `X` divided by the tokens staked at that time. The delegator allocation is `R(X) * delegator_stake`. +Then the rewards for all the delegators for staking between periods `A` and `B` are `(R(B) - R(A)) * total stake`. +However, these calculated rewards don't account for slashing. + +Taking the slashes into account requires iteration. +Let `F(X)` be the fraction a validator is to be slashed for a slashing event that happened at period `X`. +If the validator was slashed at periods `P1, ..., PN`, where `A < P1`, `PN < B`, the distribution module calculates the individual delegator's rewards, `T(A, B)`, as follows: + +```go +stake := initial stake +rewards := 0 +previous := A +for P in P1, ..., PN`: + rewards = (R(P) - previous) * stake + stake = stake * F(P) + previous = P +rewards = rewards + (R(B) - R(PN)) * stake +``` + +The historical rewards are calculated retroactively by playing back all the slashes and then attenuating the delegator's stake at each step. +The final calculated stake is equivalent to the actual staked coins in the delegation with a margin of error due to rounding errors. + +Response: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L66-L77 +``` + +### WithdrawValidatorCommission + +The validator can send the WithdrawValidatorCommission message to withdraw their accumulated commission. +The commission is calculated in every block during `BeginBlock`, so no iteration is required to withdraw. +The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator. +Only integer amounts can be sent. If the accumulated awards have decimals, the amount is truncated before the withdrawal is sent, and the remainder is left to be withdrawn later. + +### FundCommunityPool + +This message sends coins directly from the sender to the community pool. + +The transaction fails if the amount cannot be transferred from the sender to the distribution module account. + +```go +func (k Keeper) FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error { + if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount); err != nil { + return err + } + + feePool := k.GetFeePool(ctx) + feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...) + k.SetFeePool(ctx, feePool) + + return nil +} +``` + +### Common distribution operations + +These operations take place during many different messages. + +#### Initialize delegation + +Each time a delegation is changed, the rewards are withdrawn and the delegation is reinitialized. +Initializing a delegation increments the validator period and keeps track of the starting period of the delegation. + +```go +// initialize starting info for a new delegation +func (k Keeper) initializeDelegation(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress) { + // period has already been incremented - we want to store the period ended by this delegation action + previousPeriod := k.GetValidatorCurrentRewards(ctx, val).Period - 1 + + // increment reference count for the period we're going to track + k.incrementReferenceCount(ctx, val, previousPeriod) + + validator := k.stakingKeeper.Validator(ctx, val) + delegation := k.stakingKeeper.Delegation(ctx, del, val) + + // calculate delegation stake in tokens + // we don't store directly, so multiply delegation shares * (tokens per share) + // note: necessary to truncate so we don't allow withdrawing more rewards than owed + stake := validator.TokensFromSharesTruncated(delegation.GetShares()) + k.SetDelegatorStartingInfo(ctx, val, del, types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight()))) +} +``` + +### MsgUpdateParams + +Distribution module params can be updated through `MsgUpdateParams`, which can be done using governance proposal and the signer will always be gov module account address. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L133-L147 +``` + +The message handling can fail if: + +* signer is not the gov module account address. + +## Hooks + +Available hooks that can be called by and from this module. + +### Create or modify delegation distribution + +* triggered-by: `staking.MsgDelegate`, `staking.MsgBeginRedelegate`, `staking.MsgUndelegate` + +#### Before + +* The delegation rewards are withdrawn to the withdraw address of the delegator. + The rewards include the current period and exclude the starting period. +* The validator period is incremented. + The validator period is incremented because the validator's power and share distribution might have changed. +* The reference count for the delegator's starting period is decremented. + +#### After + +The starting height of the delegation is set to the previous period. +Because of the `Before`-hook, this period is the last period for which the delegator was rewarded. + +### Validator created + +* triggered-by: `staking.MsgCreateValidator` + +When a validator is created, the following validator variables are initialized: + +* Historical rewards +* Current accumulated rewards +* Accumulated commission +* Total outstanding rewards +* Period + +By default, all values are set to a `0`, except period, which is set to `1`. + +### Validator removed + +* triggered-by: `staking.RemoveValidator` + +Outstanding commission is sent to the validator's self-delegation withdrawal address. +Remaining delegator rewards get sent to the community fee pool. + +Note: The validator gets removed only when it has no remaining delegations. +At that time, all outstanding delegator rewards will have been withdrawn. +Any remaining rewards are dust amounts. + +### Validator is slashed + +* triggered-by: `staking.Slash` +* The current validator period reference count is incremented. + The reference count is incremented because the slash event has created a reference to it. +* The validator period is incremented. +* The slash event is stored for later use. + The slash event will be referenced when calculating delegator rewards. + +## Events + +The distribution module emits the following events: + +### BeginBlocker + +| Type | Attribute Key | Attribute Value | +|-----------------|---------------|--------------------| +| proposer_reward | validator | {validatorAddress} | +| proposer_reward | reward | {proposerReward} | +| commission | amount | {commissionAmount} | +| commission | validator | {validatorAddress} | +| rewards | amount | {rewardAmount} | +| rewards | validator | {validatorAddress} | + +### Handlers + +#### MsgSetWithdrawAddress + +| Type | Attribute Key | Attribute Value | +|----------------------|------------------|----------------------| +| set_withdraw_address | withdraw_address | {withdrawAddress} | +| message | module | distribution | +| message | action | set_withdraw_address | +| message | sender | {senderAddress} | + +#### MsgWithdrawDelegatorReward + +| Type | Attribute Key | Attribute Value | +|---------|---------------|---------------------------| +| withdraw_rewards | amount | {rewardAmount} | +| withdraw_rewards | validator | {validatorAddress} | +| message | module | distribution | +| message | action | withdraw_delegator_reward | +| message | sender | {senderAddress} | + +#### MsgWithdrawValidatorCommission + +| Type | Attribute Key | Attribute Value | +|------------|---------------|-------------------------------| +| withdraw_commission | amount | {commissionAmount} | +| message | module | distribution | +| message | action | withdraw_validator_commission | +| message | sender | {senderAddress} | + +## Parameters + +The distribution module contains the following parameters: + +| Key | Type | Example | +| ------------------- | ------------ | -------------------------- | +| communitytax | string (dec) | "0.020000000000000000" [0] | +| withdrawaddrenabled | bool | true | + +* [0] `communitytax` must be positive and cannot exceed 1.00. +* `baseproposerreward` and `bonusproposerreward` were parameters that are deprecated in v0.47 and are not used. + +:::note +The reserve pool is the pool of collected funds for use by governance taken via the `CommunityTax`. +Currently with the Cosmos SDK, tokens collected by the CommunityTax are accounted for but unspendable. +::: + +## Client + +## CLI + +A user can query and interact with the `distribution` module using the CLI. + +#### Query + +The `query` commands allow users to query `distribution` state. + +```shell +simd query distribution --help +``` + +##### commission + +The `commission` command allows users to query validator commission rewards by address. + +```shell +simd query distribution commission [address] [flags] +``` + +Example: + +```shell +simd query distribution commission cosmosvaloper1... +``` + +Example Output: + +```yml +commission: +- amount: "1000000.000000000000000000" + denom: stake +``` + +##### community-pool + +The `community-pool` command allows users to query all coin balances within the community pool. + +```shell +simd query distribution community-pool [flags] +``` + +Example: + +```shell +simd query distribution community-pool +``` + +Example Output: + +```yml +pool: +- amount: "1000000.000000000000000000" + denom: stake +``` + +##### params + +The `params` command allows users to query the parameters of the `distribution` module. + +```shell +simd query distribution params [flags] +``` + +Example: + +```shell +simd query distribution params +``` + +Example Output: + +```yml +base_proposer_reward: "0.000000000000000000" +bonus_proposer_reward: "0.000000000000000000" +community_tax: "0.020000000000000000" +withdraw_addr_enabled: true +``` + +##### rewards + +The `rewards` command allows users to query delegator rewards. Users can optionally include the validator address to query rewards earned from a specific validator. + +```shell +simd query distribution rewards [delegator-addr] [validator-addr] [flags] +``` + +Example: + +```shell +simd query distribution rewards cosmos1... +``` + +Example Output: + +```yml +rewards: +- reward: + - amount: "1000000.000000000000000000" + denom: stake + validator_address: cosmosvaloper1.. +total: +- amount: "1000000.000000000000000000" + denom: stake +``` + +##### slashes + +The `slashes` command allows users to query all slashes for a given block range. + +```shell +simd query distribution slashes [validator] [start-height] [end-height] [flags] +``` + +Example: + +```shell +simd query distribution slashes cosmosvaloper1... 1 1000 +``` + +Example Output: + +```yml +pagination: + next_key: null + total: "0" +slashes: +- validator_period: 20, + fraction: "0.009999999999999999" +``` + +##### validator-outstanding-rewards + +The `validator-outstanding-rewards` command allows users to query all outstanding (un-withdrawn) rewards for a validator and all their delegations. + +```shell +simd query distribution validator-outstanding-rewards [validator] [flags] +``` + +Example: + +```shell +simd query distribution validator-outstanding-rewards cosmosvaloper1... +``` + +Example Output: + +```yml +rewards: +- amount: "1000000.000000000000000000" + denom: stake +``` + +##### validator-distribution-info + +The `validator-distribution-info` command allows users to query validator commission and self-delegation rewards for validator. + +```shell +simd query distribution validator-distribution-info cosmosvaloper1... +``` + +Example Output: + +```yml +commission: +- amount: "100000.000000000000000000" + denom: stake +operator_address: cosmosvaloper1... +self_bond_rewards: +- amount: "100000.000000000000000000" + denom: stake +``` + +#### Transactions + +The `tx` commands allow users to interact with the `distribution` module. + +```shell +simd tx distribution --help +``` + +##### fund-community-pool + +The `fund-community-pool` command allows users to send funds to the community pool. + +```shell +simd tx distribution fund-community-pool [amount] [flags] +``` + +Example: + +```shell +simd tx distribution fund-community-pool 100stake --from cosmos1... +``` + +##### set-withdraw-addr + +The `set-withdraw-addr` command allows users to set the withdraw address for rewards associated with a delegator address. + +```shell +simd tx distribution set-withdraw-addr [withdraw-addr] [flags] +``` + +Example: + +```shell +simd tx distribution set-withdraw-addr cosmos1... --from cosmos1... +``` + +##### withdraw-all-rewards + +The `withdraw-all-rewards` command allows users to withdraw all rewards for a delegator. + +```shell +simd tx distribution withdraw-all-rewards [flags] +``` + +Example: + +```shell +simd tx distribution withdraw-all-rewards --from cosmos1... +``` + +##### withdraw-rewards + +The `withdraw-rewards` command allows users to withdraw all rewards from a given delegation address, +and optionally withdraw validator commission if the delegation address given is a validator operator and the user proves the `--commission` flag. + +```shell +simd tx distribution withdraw-rewards [validator-addr] [flags] +``` + +Example: + +```shell +simd tx distribution withdraw-rewards cosmosvaloper1... --from cosmos1... --commission +``` + +### gRPC + +A user can query the `distribution` module using gRPC endpoints. + +#### Params + +The `Params` endpoint allows users to query parameters of the `distribution` module. + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/Params +``` + +Example Output: + +```json +{ + "params": { + "communityTax": "20000000000000000", + "baseProposerReward": "00000000000000000", + "bonusProposerReward": "00000000000000000", + "withdrawAddrEnabled": true + } +} +``` + +#### ValidatorDistributionInfo + +The `ValidatorDistributionInfo` queries validator commission and self-delegation rewards for validator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"validator_address":"cosmosvalop1..."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/ValidatorDistributionInfo +``` + +Example Output: + +```json +{ + "commission": { + "commission": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] + }, + "self_bond_rewards": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ], + "validator_address": "cosmosvalop1..." +} +``` + +#### ValidatorOutstandingRewards + +The `ValidatorOutstandingRewards` endpoint allows users to query rewards of a validator address. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"validator_address":"cosmosvalop1.."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/ValidatorOutstandingRewards +``` + +Example Output: + +```json +{ + "rewards": { + "rewards": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] + } +} +``` + +#### ValidatorCommission + +The `ValidatorCommission` endpoint allows users to query accumulated commission for a validator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"validator_address":"cosmosvalop1.."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/ValidatorCommission +``` + +Example Output: + +```json +{ + "commission": { + "commission": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] + } +} +``` + +#### ValidatorSlashes + +The `ValidatorSlashes` endpoint allows users to query slash events of a validator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"validator_address":"cosmosvalop1.."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/ValidatorSlashes +``` + +Example Output: + +```json +{ + "slashes": [ + { + "validator_period": "20", + "fraction": "0.009999999999999999" + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### DelegationRewards + +The `DelegationRewards` endpoint allows users to query the total rewards accrued by a delegation. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"delegator_address":"cosmos1...","validator_address":"cosmosvalop1..."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/DelegationRewards +``` + +Example Output: + +```json +{ + "rewards": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] +} +``` + +#### DelegationTotalRewards + +The `DelegationTotalRewards` endpoint allows users to query the total rewards accrued by each validator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"delegator_address":"cosmos1..."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/DelegationTotalRewards +``` + +Example Output: + +```json +{ + "rewards": [ + { + "validatorAddress": "cosmosvaloper1...", + "reward": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] + } + ], + "total": [ + { + "denom": "stake", + "amount": "1000000000000000" + } + ] +} +``` + +#### DelegatorValidators + +The `DelegatorValidators` endpoint allows users to query all validators for given delegator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"delegator_address":"cosmos1..."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/DelegatorValidators +``` + +Example Output: + +```json +{ + "validators": ["cosmosvaloper1..."] +} +``` + +#### DelegatorWithdrawAddress + +The `DelegatorWithdrawAddress` endpoint allows users to query the withdraw address of a delegator. + +Example: + +```shell +grpcurl -plaintext \ + -d '{"delegator_address":"cosmos1..."}' \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress +``` + +Example Output: + +```json +{ + "withdrawAddress": "cosmos1..." +} +``` + +#### CommunityPool + +The `CommunityPool` endpoint allows users to query the community pool coins. + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + cosmos.distribution.v1beta1.Query/CommunityPool +``` + +Example Output: + +```json +{ + "pool": [ + { + "denom": "stake", + "amount": "1000000000000000000" + } + ] +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/evidence/README.md b/versioned_docs/version-0.47/integrate/modules/evidence/README.md new file mode 100644 index 000000000..263481b0c --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/evidence/README.md @@ -0,0 +1,440 @@ +--- +sidebar_position: 1 +--- + +# `x/evidence` + +* [Concepts](#concepts) +* [State](#state) +* [Messages](#messages) +* [Events](#events) +* [Parameters](#parameters) +* [BeginBlock](#beginblock) +* [Client](#client) + * [CLI](#cli) + * [REST](#rest) + * [gRPC](#grpc) + +## Abstract + +`x/evidence` is an implementation of a Cosmos SDK module, per [ADR 009](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-009-evidence-module.md), +that allows for the submission and handling of arbitrary evidence of misbehavior such +as equivocation and counterfactual signing. + +The evidence module differs from standard evidence handling which typically expects the +underlying consensus engine, e.g. CometBFT, to automatically submit evidence when +it is discovered by allowing clients and foreign chains to submit more complex evidence +directly. + +All concrete evidence types must implement the `Evidence` interface contract. Submitted +`Evidence` is first routed through the evidence module's `Router` in which it attempts +to find a corresponding registered `Handler` for that specific `Evidence` type. +Each `Evidence` type must have a `Handler` registered with the evidence module's +keeper in order for it to be successfully routed and executed. + +Each corresponding handler must also fulfill the `Handler` interface contract. The +`Handler` for a given `Evidence` type can perform any arbitrary state transitions +such as slashing, jailing, and tombstoning. + +## Concepts + +### Evidence + +Any concrete type of evidence submitted to the `x/evidence` module must fulfill the +`Evidence` contract outlined below. Not all concrete types of evidence will fulfill +this contract in the same way and some data may be entirely irrelevant to certain +types of evidence. An additional `ValidatorEvidence`, which extends `Evidence`, +has also been created to define a contract for evidence against malicious validators. + +```go +// Evidence defines the contract which concrete evidence types of misbehavior +// must implement. +type Evidence interface { + proto.Message + + Route() string + String() string + Hash() []byte + ValidateBasic() error + + // Height at which the infraction occurred + GetHeight() int64 +} + +// ValidatorEvidence extends Evidence interface to define contract +// for evidence against malicious validators +type ValidatorEvidence interface { + Evidence + + // The consensus address of the malicious validator at time of infraction + GetConsensusAddress() sdk.ConsAddress + + // The total power of the malicious validator at time of infraction + GetValidatorPower() int64 + + // The total validator set power at time of infraction + GetTotalPower() int64 +} +``` + +### Registration & Handling + +The `x/evidence` module must first know about all types of evidence it is expected +to handle. This is accomplished by registering the `Route` method in the `Evidence` +contract with what is known as a `Router` (defined below). The `Router` accepts +`Evidence` and attempts to find the corresponding `Handler` for the `Evidence` +via the `Route` method. + +```go +type Router interface { + AddRoute(r string, h Handler) Router + HasRoute(r string) bool + GetRoute(path string) Handler + Seal() + Sealed() bool +} +``` + +The `Handler` (defined below) is responsible for executing the entirety of the +business logic for handling `Evidence`. This typically includes validating the +evidence, both stateless checks via `ValidateBasic` and stateful checks via any +keepers provided to the `Handler`. In addition, the `Handler` may also perform +capabilities such as slashing and jailing a validator. All `Evidence` handled +by the `Handler` should be persisted. + +```go +// Handler defines an agnostic Evidence handler. The handler is responsible +// for executing all corresponding business logic necessary for verifying the +// evidence as valid. In addition, the Handler may execute any necessary +// slashing and potential jailing. +type Handler func(sdk.Context, Evidence) error +``` + + +## State + +Currently the `x/evidence` module only stores valid submitted `Evidence` in state. +The evidence state is also stored and exported in the `x/evidence` module's `GenesisState`. + +```protobuf +// GenesisState defines the evidence module's genesis state. +message GenesisState { + // evidence defines all the evidence at genesis. + repeated google.protobuf.Any evidence = 1; +} + +``` + +All `Evidence` is retrieved and stored via a prefix `KVStore` using prefix `0x00` (`KeyPrefixEvidence`). + + +## Messages + +### MsgSubmitEvidence + +Evidence is submitted through a `MsgSubmitEvidence` message: + +```protobuf +// MsgSubmitEvidence represents a message that supports submitting arbitrary +// Evidence of misbehavior such as equivocation or counterfactual signing. +message MsgSubmitEvidence { + string submitter = 1; + google.protobuf.Any evidence = 2; +} +``` + +Note, the `Evidence` of a `MsgSubmitEvidence` message must have a corresponding +`Handler` registered with the `x/evidence` module's `Router` in order to be processed +and routed correctly. + +Given the `Evidence` is registered with a corresponding `Handler`, it is processed +as follows: + +```go +func SubmitEvidence(ctx Context, evidence Evidence) error { + if _, ok := GetEvidence(ctx, evidence.Hash()); ok { + return errorsmod.Wrap(types.ErrEvidenceExists, strings.ToUpper(hex.EncodeToString(evidence.Hash()))) + } + if !router.HasRoute(evidence.Route()) { + return errorsmod.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route()) + } + + handler := router.GetRoute(evidence.Route()) + if err := handler(ctx, evidence); err != nil { + return errorsmod.Wrap(types.ErrInvalidEvidence, err.Error()) + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeSubmitEvidence, + sdk.NewAttribute(types.AttributeKeyEvidenceHash, strings.ToUpper(hex.EncodeToString(evidence.Hash()))), + ), + ) + + SetEvidence(ctx, evidence) + return nil +} +``` + +First, there must not already exist valid submitted `Evidence` of the exact same +type. Secondly, the `Evidence` is routed to the `Handler` and executed. Finally, +if there is no error in handling the `Evidence`, an event is emitted and it is persisted to state. + + +## Events + +The `x/evidence` module emits the following events: + +### Handlers + +#### MsgSubmitEvidence + +| Type | Attribute Key | Attribute Value | +| --------------- | ------------- | --------------- | +| submit_evidence | evidence_hash | {evidenceHash} | +| message | module | evidence | +| message | sender | {senderAddress} | +| message | action | submit_evidence | + + +## Parameters + +The evidence module does not contain any parameters. + + +## BeginBlock + +### Evidence Handling + +CometBFT blocks can include +[Evidence](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_basic_concepts.md#evidence) that indicates if a validator committed malicious behavior. The relevant information is forwarded to the application as ABCI Evidence in `abci.RequestBeginBlock` so that the validator can be punished accordingly. + +#### Equivocation + +The Cosmos SDK handles two types of evidence inside the ABCI `BeginBlock`: + +* `DuplicateVoteEvidence`, +* `LightClientAttackEvidence`. + +The evidence module handles these two evidence types the same way. First, the Cosmos SDK converts the CometBFT concrete evidence type to an SDK `Evidence` interface using `Equivocation` as the concrete type. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/evidence/v1beta1/evidence.proto#L12-L32 +``` + +For some `Equivocation` submitted in `block` to be valid, it must satisfy: + +`Evidence.Timestamp >= block.Timestamp - MaxEvidenceAge` + +Where: + +* `Evidence.Timestamp` is the timestamp in the block at height `Evidence.Height` +* `block.Timestamp` is the current block timestamp. + +If valid `Equivocation` evidence is included in a block, the validator's stake is +reduced (slashed) by `SlashFractionDoubleSign` as defined by the `x/slashing` module +of what their stake was when the infraction occurred, rather than when the evidence was discovered. +We want to "follow the stake", i.e., the stake that contributed to the infraction +should be slashed, even if it has since been redelegated or started unbonding. + +In addition, the validator is permanently jailed and tombstoned to make it impossible for that +validator to ever re-enter the validator set. + +The `Equivocation` evidence is handled as follows: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/evidence/keeper/infraction.go#L26-L140 +``` + +**Note:** The slashing, jailing, and tombstoning calls are delegated through the `x/slashing` module +that emits informative events and finally delegates calls to the `x/staking` module. See documentation +on slashing and jailing in [State Transitions](../staking/README.md#state-transitions). + +## Client + +### CLI + +A user can query and interact with the `evidence` module using the CLI. + +#### Query + +The `query` commands allows users to query `evidence` state. + +```bash +simd query evidence --help +``` + +#### evidence + +The `evidence` command allows users to list all evidence or evidence by hash. + +Usage: + +```bash +simd query evidence [flags] +``` + +To query evidence by hash + +Example: + +```bash +simd query evidence "DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660" +``` + +Example Output: + +```bash +evidence: + consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h + height: 11 + power: 100 + time: "2021-10-20T16:08:38.194017624Z" +``` + +To get all evidence + +Example: + +```bash +simd query evidence +``` + +Example Output: + +```bash +evidence: + consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h + height: 11 + power: 100 + time: "2021-10-20T16:08:38.194017624Z" +pagination: + next_key: null + total: "1" +``` + +### REST + +A user can query the `evidence` module using REST endpoints. + +#### Evidence + +Get evidence by hash + +```bash +/cosmos/evidence/v1beta1/evidence/{hash} +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence/DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660" +``` + +Example Output: + +```bash +{ + "evidence": { + "consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h", + "height": "11", + "power": "100", + "time": "2021-10-20T16:08:38.194017624Z" + } +} +``` + +#### All evidence + +Get all evidence + +```bash +/cosmos/evidence/v1beta1/evidence +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence" +``` + +Example Output: + +```bash +{ + "evidence": [ + { + "consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h", + "height": "11", + "power": "100", + "time": "2021-10-20T16:08:38.194017624Z" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### gRPC + +A user can query the `evidence` module using gRPC endpoints. + +#### Evidence + +Get evidence by hash + +```bash +cosmos.evidence.v1beta1.Query/Evidence +``` + +Example: + +```bash +grpcurl -plaintext -d '{"evidence_hash":"DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"}' localhost:9090 cosmos.evidence.v1beta1.Query/Evidence +``` + +Example Output: + +```bash +{ + "evidence": { + "consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h", + "height": "11", + "power": "100", + "time": "2021-10-20T16:08:38.194017624Z" + } +} +``` + +#### All evidence + +Get all evidence + +```bash +cosmos.evidence.v1beta1.Query/AllEvidence +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.evidence.v1beta1.Query/AllEvidence +``` + +Example Output: + +```bash +{ + "evidence": [ + { + "consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h", + "height": "11", + "power": "100", + "time": "2021-10-20T16:08:38.194017624Z" + } + ], + "pagination": { + "total": "1" + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/feegrant/README.md b/versioned_docs/version-0.47/integrate/modules/feegrant/README.md new file mode 100644 index 000000000..9fcd1e476 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/feegrant/README.md @@ -0,0 +1,388 @@ +--- +sidebar_position: 1 +--- + +# `x/feegrant` + +## Abstract + +This document specifies the fee grant module. For the full ADR, please see [Fee Grant ADR-029](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-029-fee-grant-module.md). + +This module allows accounts to grant fee allowances and to use fees from their accounts. Grantees can execute any transaction without the need to maintain sufficient fees. + +## Contents + +* [Concepts](#concepts) +* [State](#state) + * [FeeAllowance](#feeallowance) + * [FeeAllowanceQueue](#feeallowancequeue) +* [Messages](#messages) + * [Msg/GrantAllowance](#msggrantallowance) + * [Msg/RevokeAllowance](#msgrevokeallowance) +* [Events](#events) +* [Msg Server](#msg-server) + * [MsgGrantAllowance](#msggrantallowance-1) + * [MsgRevokeAllowance](#msgrevokeallowance-1) + * [Exec fee allowance](#exec-fee-allowance) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + +## Concepts + +### Grant + +`Grant` is stored in the KVStore to record a grant with full context. Every grant will contain `granter`, `grantee` and what kind of `allowance` is granted. `granter` is an account address who is giving permission to `grantee` (the beneficiary account address) to pay for some or all of `grantee`'s transaction fees. `allowance` defines what kind of fee allowance (`BasicAllowance` or `PeriodicAllowance`, see below) is granted to `grantee`. `allowance` accepts an interface which implements `FeeAllowanceI`, encoded as `Any` type. There can be only one existing fee grant allowed for a `grantee` and `granter`, self grants are not allowed. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/feegrant.proto#L83-L93 +``` + +`FeeAllowanceI` looks like: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/feegrant/fees.go#L9-L32 +``` + +### Fee Allowance types + +There are two types of fee allowances present at the moment: + +* `BasicAllowance` +* `PeriodicAllowance` +* `AllowedMsgAllowance` + +### BasicAllowance + +`BasicAllowance` is permission for `grantee` to use fee from a `granter`'s account. If any of the `spend_limit` or `expiration` reaches its limit, the grant will be removed from the state. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/feegrant.proto#L15-L28 +``` + +* `spend_limit` is the limit of coins that are allowed to be used from the `granter` account. If it is empty, it assumes there's no spend limit, `grantee` can use any number of available coins from `granter` account address before the expiration. + +* `expiration` specifies an optional time when this allowance expires. If the value is left empty, there is no expiry for the grant. + +* When a grant is created with empty values for `spend_limit` and `expiration`, it is still a valid grant. It won't restrict the `grantee` to use any number of coins from `granter` and it won't have any expiration. The only way to restrict the `grantee` is by revoking the grant. + +### PeriodicAllowance + +`PeriodicAllowance` is a repeating fee allowance for the mentioned period, we can mention when the grant can expire as well as when a period can reset. We can also define the maximum number of coins that can be used in a mentioned period of time. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/feegrant.proto#L34-L68 +``` + +* `basic` is the instance of `BasicAllowance` which is optional for periodic fee allowance. If empty, the grant will have no `expiration` and no `spend_limit`. + +* `period` is the specific period of time, after each period passes, `period_can_spend` will be reset. + +* `period_spend_limit` specifies the maximum number of coins that can be spent in the period. + +* `period_can_spend` is the number of coins left to be spent before the period_reset time. + +* `period_reset` keeps track of when a next period reset should happen. + +### AllowedMsgAllowance + +`AllowedMsgAllowance` is a fee allowance, it can be any of `BasicFeeAllowance`, `PeriodicAllowance` but restricted only to the allowed messages mentioned by the granter. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/feegrant.proto#L70-L81 +``` + +* `allowance` is either `BasicAllowance` or `PeriodicAllowance`. + +* `allowed_messages` is array of messages allowed to execute the given allowance. + +### FeeGranter flag + +`feegrant` module introduces a `FeeGranter` flag for CLI for the sake of executing transactions with fee granter. When this flag is set, `clientCtx` will append the granter account address for transactions generated through CLI. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/cmd.go#L249-L260 +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/client/tx/tx.go#L109-L109 +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/auth/tx/builder.go#L275-L284 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/tx/v1beta1/tx.proto#L203-L224 +``` + +Example cmd: + +```go +./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-granter=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake" +``` + +### Granted Fee Deductions + +Fees are deducted from grants in the `x/auth` ante handler. To learn more about how ante handlers work, read the [Auth Module AnteHandlers Guide](../auth/README.md#antehandlers). + +### Gas + +In order to prevent DoS attacks, using a filtered `x/feegrant` incurs gas. The SDK must assure that the `grantee`'s transactions all conform to the filter set by the `granter`. The SDK does this by iterating over the allowed messages in the filter and charging 10 gas per filtered message. The SDK will then iterate over the messages being sent by the `grantee` to ensure the messages adhere to the filter, also charging 10 gas per message. The SDK will stop iterating and fail the transaction if it finds a message that does not conform to the filter. + +**WARNING**: The gas is charged against the granted allowance. Ensure your messages conform to the filter, if any, before sending transactions using your allowance. + +### Pruning + +A queue in the state maintained with the prefix of expiration of the grants and checks them on EndBlock with the current block time for every block to prune. + +## State + +### FeeAllowance + +Fee Allowances are identified by combining `Grantee` (the account address of fee allowance grantee) with the `Granter` (the account address of fee allowance granter). + +Fee allowance grants are stored in the state as follows: + +* Grant: `0x00 | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> ProtocolBuffer(Grant)` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/feegrant/feegrant.pb.go#L222-L230 +``` + +### FeeAllowanceQueue + +Fee Allowances queue items are identified by combining the `FeeAllowancePrefixQueue` (i.e., 0x01), `expiration`, `grantee` (the account address of fee allowance grantee), `granter` (the account address of fee allowance granter). Endblocker checks `FeeAllowanceQueue` state for the expired grants and prunes them from `FeeAllowance` if there are any found. + +Fee allowance queue keys are stored in the state as follows: + +* Grant: `0x01 | expiration_bytes | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> EmptyBytes` + +## Messages + +### Msg/GrantAllowance + +A fee allowance grant will be created with the `MsgGrantAllowance` message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/tx.proto#L25-L39 +``` + +### Msg/RevokeAllowance + +An allowed grant fee allowance can be removed with the `MsgRevokeAllowance` message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/feegrant/v1beta1/tx.proto#L41-L54 +``` + +## Events + +The feegrant module emits the following events: + +## Msg Server + +### MsgGrantAllowance + +| Type | Attribute Key | Attribute Value | +| ------- | ------------- | ---------------- | +| message | action | set_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### MsgRevokeAllowance + +| Type | Attribute Key | Attribute Value | +| ------- | ------------- | ---------------- | +| message | action | revoke_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### Exec fee allowance + +| Type | Attribute Key | Attribute Value | +| ------- | ------------- | ---------------- | +| message | action | use_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +## Client + +### CLI + +A user can query and interact with the `feegrant` module using the CLI. + +#### Query + +The `query` commands allow users to query `feegrant` state. + +```shell +simd query feegrant --help +``` + +##### grant + +The `grant` command allows users to query a grant for a given granter-grantee pair. + +```shell +simd query feegrant grant [granter] [grantee] [flags] +``` + +Example: + +```shell +simd query feegrant grant cosmos1.. cosmos1.. +``` + +Example Output: + +```yml +allowance: + '@type': /cosmos.feegrant.v1beta1.BasicAllowance + expiration: null + spend_limit: + - amount: "100" + denom: stake +grantee: cosmos1.. +granter: cosmos1.. +``` + +##### grants + +The `grants` command allows users to query all grants for a given grantee. + +```shell +simd query feegrant grants [grantee] [flags] +``` + +Example: + +```shell +simd query feegrant grants cosmos1.. +``` + +Example Output: + +```yml +allowances: +- allowance: + '@type': /cosmos.feegrant.v1beta1.BasicAllowance + expiration: null + spend_limit: + - amount: "100" + denom: stake + grantee: cosmos1.. + granter: cosmos1.. +pagination: + next_key: null + total: "0" +``` + +#### Transactions + +The `tx` commands allow users to interact with the `feegrant` module. + +```shell +simd tx feegrant --help +``` + +##### grant + +The `grant` command allows users to grant fee allowances to another account. The fee allowance can have an expiration date, a total spend limit, and/or a periodic spend limit. + +```shell +simd tx feegrant grant [granter] [grantee] [flags] +``` + +Example (one-time spend limit): + +```shell +simd tx feegrant grant cosmos1.. cosmos1.. --spend-limit 100stake +``` + +Example (periodic spend limit): + +```shell +simd tx feegrant grant cosmos1.. cosmos1.. --period 3600 --period-limit 10stake +``` + +##### revoke + +The `revoke` command allows users to revoke a granted fee allowance. + +```shell +simd tx feegrant revoke [granter] [grantee] [flags] +``` + +Example: + +```shell +simd tx feegrant revoke cosmos1.. cosmos1.. +``` + +### gRPC + +A user can query the `feegrant` module using gRPC endpoints. + +#### Allowance + +The `Allowance` endpoint allows users to query a granted fee allowance. + +```shell +cosmos.feegrant.v1beta1.Query/Allowance +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"grantee":"cosmos1..","granter":"cosmos1.."}' \ + localhost:9090 \ + cosmos.feegrant.v1beta1.Query/Allowance +``` + +Example Output: + +```json +{ + "allowance": { + "granter": "cosmos1..", + "grantee": "cosmos1..", + "allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]} + } +} +``` + +#### Allowances + +The `Allowances` endpoint allows users to query all granted fee allowances for a given grantee. + +```shell +cosmos.feegrant.v1beta1.Query/Allowances +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"address":"cosmos1.."}' \ + localhost:9090 \ + cosmos.feegrant.v1beta1.Query/Allowances +``` + +Example Output: + +```json +{ + "allowances": [ + { + "granter": "cosmos1..", + "grantee": "cosmos1..", + "allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]} + } + ], + "pagination": { + "total": "1" + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/genutil/README.md b/versioned_docs/version-0.47/integrate/modules/genutil/README.md new file mode 100644 index 000000000..c534b8b0d --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/genutil/README.md @@ -0,0 +1,69 @@ +# `x/genutil` + +## Concepts + +The `genutil` package contains a variaety of genesis utility functionalities for usage within a blockchain application. Namely: + +* Genesis transactions related (gentx) +* Commands for collection and creation of gentxs +* `InitChain` processing of gentxs +* Genesis file validation +* Genesis file migration +* CometBFT related initialization + * Translation of an app genesis to a CometBFT genesis + +## Client + +### CLI + +The genutil commands are available under the `genesis` subcommand. + +#### add-genesis-account + +Add a genesis account to `genesis.json`. Learn more [here](https://docs.cosmos.network/main/run-node/run-node#adding-genesis-accounts). + +#### collect-gentxs + +Collect genesis txs and output a `genesis.json` file. + +```shell +simd genesis collect-gentxs +``` + +This will create a new `genesis.json` file that includes data from all the validators (we sometimes call it the "super genesis file" to distinguish it from single-validator genesis files). + +#### gentx + +Generate a genesis tx carrying a self delegation. + +```shell +simd genesis gentx [key_name] [amount] --chain-id [chain-id] +``` + +This will create the genesis transaction for your new chain. Here `amount` should be at least `1000000000stake`. +If you provide too much or too little, you will encounter an error when starting a node. + +#### migrate + +Migrate genesis to a specified target (SDK) version. + +```shell +simd genesis migrate [target-version] +``` + +:::tip +The `migrate` command is extensible and takes a `MigrationMap`. This map is a mapping of target versions to genesis migrations functions. +When not using the default `MigrationMap`, it is recommended to still call the default `MigrationMap` corresponding the SDK version of the chain and prepend/append your own genesis migrations. +::: + +#### validate-genesis + +Validates the genesis file at the default location or at the location passed as an argument. + +```shell +simd genesis validate-genesis +``` + +:::warning +Validate genesis only validates if the genesis is valid at the **current application binary**. For validating a genesis from a previous version of the application, use the `migrate` command to migrate the genesis to the current version. +::: diff --git a/versioned_docs/version-0.47/integrate/modules/gov/README.md b/versioned_docs/version-0.47/integrate/modules/gov/README.md new file mode 100644 index 000000000..8dac16a3e --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/gov/README.md @@ -0,0 +1,2658 @@ +--- +sidebar_position: 1 +--- + +# `x/gov` + +## Abstract + +This paper specifies the Governance module of the Cosmos SDK, which was first +described in the [Cosmos Whitepaper](https://cosmos.network/about/whitepaper) in +June 2016. + +The module enables Cosmos SDK based blockchain to support an on-chain governance +system. In this system, holders of the native staking token of the chain can vote +on proposals on a 1 token 1 vote basis. Next is a list of features the module +currently supports: + +* **Proposal submission:** Users can submit proposals with a deposit. Once the +minimum deposit is reached, the proposal enters voting period. +* **Vote:** Participants can vote on proposals that reached MinDeposit +* **Inheritance and penalties:** Delegators inherit their validator's vote if +they don't vote themselves. +* **Claiming deposit:** Users that deposited on proposals can recover their +deposits if the proposal was accepted or rejected. If the proposal was vetoed, or never entered voting period, the deposit is burned. + +This module will be used in the Cosmos Hub, the first Hub in the Cosmos network. +Features that may be added in the future are described in [Future Improvements](#future-improvements). + +## Contents + +The following specification uses *ATOM* as the native staking token. The module +can be adapted to any Proof-Of-Stake blockchain by replacing *ATOM* with the native +staking token of the chain. + +* [Concepts](#concepts) + * [Proposal submission](#proposal-submission) + * [Deposit](#deposit) + * [Vote](#vote) +* [State](#state) + * [Proposals](#proposals) + * [Parameters and base types](#parameters-and-base-types) + * [Deposit](#deposit-1) + * [ValidatorGovInfo](#validatorgovinfo) + * [Stores](#stores) + * [Proposal Processing Queue](#proposal-processing-queue) + * [Legacy Proposal](#legacy-proposal) +* [Messages](#messages) + * [Proposal Submission](#proposal-submission-1) + * [Deposit](#deposit-2) + * [Vote](#vote-1) +* [Events](#events) + * [EndBlocker](#endblocker) + * [Handlers](#handlers) +* [Parameters](#parameters) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) +* [Metadata](#metadata) + * [Proposal](#proposal-3) + * [Vote](#vote-5) +* [Future Improvements](#future-improvements) + +## Concepts + +*Disclaimer: This is work in progress. Mechanisms are susceptible to change.* + +The governance process is divided in a few steps that are outlined below: + +* **Proposal submission:** Proposal is submitted to the blockchain with a + deposit. +* **Vote:** Once deposit reaches a certain value (`MinDeposit`), proposal is + confirmed and vote opens. Bonded Atom holders can then send `TxGovVote` + transactions to vote on the proposal. +* **Execution** After a period of time, the votes are tallied and depending + on the result, the messages in the proposal will be executed. + +### Proposal submission + +#### Right to submit a proposal + +Every account can submit proposals by sending a `MsgSubmitProposal` transaction. +Once a proposal is submitted, it is identified by its unique `proposalID`. + +#### Proposal Messages + +A proposal includes an array of `sdk.Msg`s which are executed automatically if the +proposal passes. The messages are executed by the governance `ModuleAccount` itself. Modules +such as `x/upgrade`, that want to allow certain messages to be executed by governance +only should add a whitelist within the respective msg server, granting the governance +module the right to execute the message once a quorum has been reached. The governance +module uses the `MsgServiceRouter` to check that these messages are correctly constructed +and have a respective path to execute on but do not perform a full validity check. + +### Deposit + +To prevent spam, proposals must be submitted with a deposit in the coins defined by +the `MinDeposit` param. + +When a proposal is submitted, it has to be accompanied with a deposit that must be +strictly positive, but can be inferior to `MinDeposit`. The submitter doesn't need +to pay for the entire deposit on their own. The newly created proposal is stored in +an *inactive proposal queue* and stays there until its deposit passes the `MinDeposit`. +Other token holders can increase the proposal's deposit by sending a `Deposit` +transaction. If a proposal doesn't pass the `MinDeposit` before the deposit end time +(the time when deposits are no longer accepted), the proposal will be destroyed: the +proposal will be removed from state and the deposit will be burned (see x/gov `EndBlocker`). +When a proposal deposit passes the `MinDeposit` threshold (even during the proposal +submission) before the deposit end time, the proposal will be moved into the +*active proposal queue* and the voting period will begin. + +The deposit is kept in escrow and held by the governance `ModuleAccount` until the +proposal is finalized (passed or rejected). + +#### Deposit refund and burn + +When a proposal is finalized, the coins from the deposit are either refunded or burned +according to the final tally of the proposal: + +* If the proposal is approved or rejected but *not* vetoed, each deposit will be + automatically refunded to its respective depositor (transferred from the governance + `ModuleAccount`). +* When the proposal is vetoed with greater than 1/3, deposits will be burned from the + governance `ModuleAccount` and the proposal information along with its deposit + information will be removed from state. +* All refunded or burned deposits are removed from the state. Events are issued when + burning or refunding a deposit. + +### Vote + +#### Participants + +*Participants* are users that have the right to vote on proposals. On the +Cosmos Hub, participants are bonded Atom holders. Unbonded Atom holders and +other users do not get the right to participate in governance. However, they +can submit and deposit on proposals. + +Note that when *participants* have bonded and unbonded Atoms, their voting power is calculated from their bonded Atom holdings only. + +#### Voting period + +Once a proposal reaches `MinDeposit`, it immediately enters `Voting period`. We +define `Voting period` as the interval between the moment the vote opens and +the moment the vote closes. `Voting period` should always be shorter than +`Unbonding period` to prevent double voting. The initial value of +`Voting period` is 2 weeks. + +#### Option set + +The option set of a proposal refers to the set of choices a participant can +choose from when casting its vote. + +The initial option set includes the following options: + +* `Yes` +* `No` +* `NoWithVeto` +* `Abstain` + +`NoWithVeto` counts as `No` but also adds a `Veto` vote. `Abstain` option +allows voters to signal that they do not intend to vote in favor or against the +proposal but accept the result of the vote. + +*Note: from the UI, for urgent proposals we should maybe add a ‘Not Urgent’ option that casts a `NoWithVeto` vote.* + +#### Weighted Votes + +[ADR-037](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md) introduces the weighted vote feature which allows a staker to split their votes into several voting options. For example, it could use 70% of its voting power to vote Yes and 30% of its voting power to vote No. + +Often times the entity owning that address might not be a single individual. For example, a company might have different stakeholders who want to vote differently, and so it makes sense to allow them to split their voting power. Currently, it is not possible for them to do "passthrough voting" and giving their users voting rights over their tokens. However, with this system, exchanges can poll their users for voting preferences, and then vote on-chain proportionally to the results of the poll. + +To represent weighted vote on chain, we use the following Protobuf message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1beta1/gov.proto#L34-L47 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1beta1/gov.proto#L181-L201 +``` + +For a weighted vote to be valid, the `options` field must not contain duplicate vote options, and the sum of weights of all options must be equal to 1. + +### Quorum + +Quorum is defined as the minimum percentage of voting power that needs to be +cast on a proposal for the result to be valid. + +### Expedited Proposals + +A proposal can be expedited, making the proposal use shorter voting duration and a higher tally threshold by its default. If an expedited proposal fails to meet the threshold within the scope of shorter voting duration, the expedited proposal is then converted to a regular proposal and restarts voting under regular voting conditions. + +#### Threshold + +Threshold is defined as the minimum proportion of `Yes` votes (excluding +`Abstain` votes) for the proposal to be accepted. + +Initially, the threshold is set at 50% of `Yes` votes, excluding `Abstain` +votes. A possibility to veto exists if more than 1/3rd of all votes are +`NoWithVeto` votes. Note, both of these values are derived from the `TallyParams` +on-chain parameter, which is modifiable by governance. +This means that proposals are accepted iff: + +* There exist bonded tokens. +* Quorum has been achieved. +* The proportion of `Abstain` votes is inferior to 1/1. +* The proportion of `NoWithVeto` votes is inferior to 1/3, including + `Abstain` votes. +* The proportion of `Yes` votes, excluding `Abstain` votes, at the end of + the voting period is superior to 1/2. + +For expedited proposals, by default, the threshold is higher than with a *normal proposal*, namely, 66.7%. + +#### Inheritance + +If a delegator does not vote, it will inherit its validator vote. + +* If the delegator votes before its validator, it will not inherit from the + validator's vote. +* If the delegator votes after its validator, it will override its validator + vote with its own. If the proposal is urgent, it is possible + that the vote will close before delegators have a chance to react and + override their validator's vote. This is not a problem, as proposals require more than 2/3rd of the total voting power to pass, when tallied at the end of the voting period. Because as little as 1/3 + 1 validation power could collude to censor transactions, non-collusion is already assumed for ranges exceeding this threshold. + +#### Validator’s punishment for non-voting + +At present, validators are not punished for failing to vote. + +#### Governance address + +Later, we may add permissioned keys that could only sign txs from certain modules. For the MVP, the `Governance address` will be the main validator address generated at account creation. This address corresponds to a different PrivKey than the CometBFT PrivKey which is responsible for signing consensus messages. Validators thus do not have to sign governance transactions with the sensitive CometBFT PrivKey. + +#### Burnable Params + +There are three parameters that define if the deposit of a proposal should be burned or returned to the depositors. + +* `BurnVoteVeto` burns the proposal deposit if the proposal gets vetoed. +* `BurnVoteQuorum` burns the proposal deposit if the proposal deposit if the vote does not reach quorum. +* `BurnProposalDepositPrevote` burns the proposal deposit if it does not enter the voting phase. + +> Note: These parameters are modifiable via governance. + +## State + +### Constitution + +`Constitution` is found in the genesis state. It is a string field intended to be used to descibe the purpose of a particular blockchain, and its expected norms. A few examples of how the constitution field can be used: + +* define the purpose of the chain, laying a foundation for its future development +* set expectations for delegators +* set expectations for validators +* define the chain's relationship to "meatspace" entities, like a foundation or corporation + +Since this is more of a social feature than a technical feature, we'll now get into some items that may have been useful to have in a genesis constitution: + +* What limitations on governance exist, if any? + * is it okay for the community to slash the wallet of a whale that they no longer feel that they want around? (viz: Juno Proposal 4 and 16) + * can governance "socially slash" a validator who is using unapproved MEV? (viz: commonwealth.im/osmosis) + * In the event of an economic emergency, what should validators do? + * Terra crash of May, 2022, saw validators choose to run a new binary with code that had not been approved by governance, because the governance token had been inflated to nothing. +* What is the purpose of the chain, specifically? + * best example of this is the Cosmos hub, where different founding groups, have different interpertations of the purpose of the network. + +This genesis entry, "constitution" hasn't been designed for existing chains, who should likely just ratify a constitution using their governance system. Instead, this is for new chains. It will allow for validators to have a much clearer idea of purpose and the expecations placed on them while operating thier nodes. Likewise, for community members, the constitution will give them some idea of what to expect from both the "chain team" and the validators, respectively. + +This constitution is designed to be immutable, and placed only in genesis, though that could change over time by a pull request to the cosmos-sdk that allows for the constitution to be changed by governance. Communities whishing to make amendments to their original constitution should use the governance mechanism and a "signaling proposal" to do exactly that. + +**Ideal use scenario for a cosmos chain constitution** + +As a chain developer, you decide that you'd like to provide clarity to your key user groups: + +* validators +* token holders +* developers (yourself) + +You use the constitution to immutably store some Markdown in genesis, so that when difficult questions come up, the constutituon can provide guidance to the community. + +### Proposals + +`Proposal` objects are used to tally votes and generally track the proposal's state. +They contain an array of arbitrary `sdk.Msg`'s which the governance module will attempt +to resolve and then execute if the proposal passes. `Proposal`'s are identified by a +unique id and contains a series of timestamps: `submit_time`, `deposit_end_time`, +`voting_start_time`, `voting_end_time` which track the lifecycle of a proposal + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L51-L99 +``` + +A proposal will generally require more than just a set of messages to explain its +purpose but need some greater justification and allow a means for interested participants +to discuss and debate the proposal. +In most cases, **it is encouraged to have an off-chain system that supports the on-chain governance process**. +To accommodate for this, a proposal contains a special **`metadata`** field, a string, +which can be used to add context to the proposal. The `metadata` field allows custom use for networks, +however, it is expected that the field contains a URL or some form of CID using a system such as +[IPFS](https://docs.ipfs.io/concepts/content-addressing/). To support the case of +interoperability across networks, the SDK recommends that the `metadata` represents +the following `JSON` template: + +```json +{ + "title": "...", + "description": "...", + "forum": "...", // a link to the discussion platform (i.e. Discord) + "other": "..." // any extra data that doesn't correspond to the other fields +} +``` + +This makes it far easier for clients to support multiple networks. + +The metadata has a maximum length that is chosen by the app developer, and +passed into the gov keeper as a config. The default maximum length in the SDK is 255 characters. + +#### Writing a module that uses governance + +There are many aspects of a chain, or of the individual modules that you may want to +use governance to perform such as changing various parameters. This is very simple +to do. First, write out your message types and `MsgServer` implementation. Add an +`authority` field to the keeper which will be populated in the constructor with the +governance module account: `govKeeper.GetGovernanceAccount().GetAddress()`. Then for +the methods in the `msg_server.go`, perform a check on the message that the signer +matches `authority`. This will prevent any user from executing that message. + +### Parameters and base types + +`Parameters` define the rules according to which votes are run. There can only +be one active parameter set at any given time. If governance wants to change a +parameter set, either to modify a value or add/remove a parameter field, a new +parameter set has to be created and the previous one rendered inactive. + +#### DepositParams + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L152-L162 +``` + +#### VotingParams + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L164-L168 +``` + +#### TallyParams + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L170-L182 +``` + +Parameters are stored in a global `GlobalParams` KVStore. + +Additionally, we introduce some basic types: + +```go +type Vote byte + +const ( + VoteYes = 0x1 + VoteNo = 0x2 + VoteNoWithVeto = 0x3 + VoteAbstain = 0x4 +) + +type ProposalType string + +const ( + ProposalTypePlainText = "Text" + ProposalTypeSoftwareUpgrade = "SoftwareUpgrade" +) + +type ProposalStatus byte + + +const ( + StatusNil ProposalStatus = 0x00 + StatusDepositPeriod ProposalStatus = 0x01 // Proposal is submitted. Participants can deposit on it but not vote + StatusVotingPeriod ProposalStatus = 0x02 // MinDeposit is reached, participants can vote + StatusPassed ProposalStatus = 0x03 // Proposal passed and successfully executed + StatusRejected ProposalStatus = 0x04 // Proposal has been rejected + StatusFailed ProposalStatus = 0x05 // Proposal passed but failed execution +) +``` + +### Deposit + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L38-L49 +``` + +### ValidatorGovInfo + +This type is used in a temp map when tallying + +```go + type ValidatorGovInfo struct { + Minus sdk.Dec + Vote Vote + } +``` + +## Stores + +:::note +Stores are KVStores in the multi-store. The key to find the store is the first parameter in the list +::: + +We will use one KVStore `Governance` to store four mappings: + +* A mapping from `proposalID|'proposal'` to `Proposal`. +* A mapping from `proposalID|'addresses'|address` to `Vote`. This mapping allows + us to query all addresses that voted on the proposal along with their vote by + doing a range query on `proposalID:addresses`. +* A mapping from `ParamsKey|'Params'` to `Params`. This map allows to query all + x/gov params. +* A mapping from `VotingPeriodProposalKeyPrefix|proposalID` to a single byte. This allows + us to know if a proposal is in the voting period or not with very low gas cost. + +For pseudocode purposes, here are the two function we will use to read or write in stores: + +* `load(StoreKey, Key)`: Retrieve item stored at key `Key` in store found at key `StoreKey` in the multistore +* `store(StoreKey, Key, value)`: Write value `Value` at key `Key` in store found at key `StoreKey` in the multistore + +### Proposal Processing Queue + +**Store:** + +* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the + `ProposalIDs` of proposals that reached `MinDeposit`. During each `EndBlock`, + all the proposals that have reached the end of their voting period are processed. + To process a finished proposal, the application tallies the votes, computes the + votes of each validator and checks if every validator in the validator set has + voted. If the proposal is accepted, deposits are refunded. Finally, the proposal + content `Handler` is executed. + +And the pseudocode for the `ProposalProcessingQueue`: + +```go + in EndBlock do + + for finishedProposalID in GetAllFinishedProposalIDs(block.Time) + proposal = load(Governance, ) // proposal is a const key + + validators = Keeper.getAllValidators() + tmpValMap := map(sdk.AccAddress)ValidatorGovInfo + + // Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes + for each validator in validators + tmpValMap(validator.OperatorAddr).Minus = 0 + + // Tally + voterIterator = rangeQuery(Governance, ) //return all the addresses that voted on the proposal + for each (voterAddress, vote) in voterIterator + delegations = stakingKeeper.getDelegations(voterAddress) // get all delegations for current voter + + for each delegation in delegations + // make sure delegation.Shares does NOT include shares being unbonded + tmpValMap(delegation.ValidatorAddr).Minus += delegation.Shares + proposal.updateTally(vote, delegation.Shares) + + _, isVal = stakingKeeper.getValidator(voterAddress) + if (isVal) + tmpValMap(voterAddress).Vote = vote + + tallyingParam = load(GlobalParams, 'TallyingParam') + + // Update tally if validator voted + for each validator in validators + if tmpValMap(validator).HasVoted + proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus)) + + + + // Check if proposal is accepted or rejected + totalNonAbstain := proposal.YesVotes + proposal.NoVotes + proposal.NoWithVetoVotes + if (proposal.Votes.YesVotes/totalNonAbstain > tallyingParam.Threshold AND proposal.Votes.NoWithVetoVotes/totalNonAbstain < tallyingParam.Veto) + // proposal was accepted at the end of the voting period + // refund deposits (non-voters already punished) + for each (amount, depositor) in proposal.Deposits + depositor.AtomBalance += amount + + stateWriter, err := proposal.Handler() + if err != nil + // proposal passed but failed during state execution + proposal.CurrentStatus = ProposalStatusFailed + else + // proposal pass and state is persisted + proposal.CurrentStatus = ProposalStatusAccepted + stateWriter.save() + else + // proposal was rejected + proposal.CurrentStatus = ProposalStatusRejected + + store(Governance, , proposal) +``` + +### Legacy Proposal + +A legacy proposal is the old implementation of governance proposal. +Contrary to proposal that can contain any messages, a legacy proposal allows to submit a set of pre-defined proposals. +These proposal are defined by their types. + +While proposals should use the new implementation of the governance proposal, we need still to use legacy proposal in order to submit a `software-upgrade` and a `cancel-software-upgrade` proposal. + +More information on how to submit proposals in the [client section](#client). + +## Messages + +### Proposal Submission + +Proposals can be submitted by any account via a `MsgSubmitProposal` transaction. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L42-L69 +``` + +All `sdk.Msgs` passed into the `messages` field of a `MsgSubmitProposal` message +must be registered in the app's `MsgServiceRouter`. Each of these messages must +have one signer, namely the gov module account. And finally, the metadata length +must not be larger than the `maxMetadataLen` config passed into the gov keeper. + +**State modifications:** + +* Generate new `proposalID` +* Create new `Proposal` +* Initialise `Proposal`'s attributes +* Decrease balance of sender by `InitialDeposit` +* If `MinDeposit` is reached: + * Push `proposalID` in `ProposalProcessingQueue` +* Transfer `InitialDeposit` from the `Proposer` to the governance `ModuleAccount` + +A `MsgSubmitProposal` transaction can be handled according to the following +pseudocode. + +```go +// PSEUDOCODE // +// Check if MsgSubmitProposal is valid. If it is, create proposal // + +upon receiving txGovSubmitProposal from sender do + + if !correctlyFormatted(txGovSubmitProposal) + // check if proposal is correctly formatted and the messages have routes to other modules. Includes fee payment. + // check if all messages' unique Signer is the gov acct. + // check if the metadata is not too long. + throw + + initialDeposit = txGovSubmitProposal.InitialDeposit + if (initialDeposit.Atoms <= 0) OR (sender.AtomBalance < initialDeposit.Atoms) + // InitialDeposit is negative or null OR sender has insufficient funds + throw + + if (txGovSubmitProposal.Type != ProposalTypePlainText) OR (txGovSubmitProposal.Type != ProposalTypeSoftwareUpgrade) + + sender.AtomBalance -= initialDeposit.Atoms + + depositParam = load(GlobalParams, 'DepositParam') + + proposalID = generate new proposalID + proposal = NewProposal() + + proposal.Messages = txGovSubmitProposal.Messages + proposal.Metadata = txGovSubmitProposal.Metadata + proposal.TotalDeposit = initialDeposit + proposal.SubmitTime = + proposal.DepositEndTime = .Add(depositParam.MaxDepositPeriod) + proposal.Deposits.append({initialDeposit, sender}) + proposal.Submitter = sender + proposal.YesVotes = 0 + proposal.NoVotes = 0 + proposal.NoWithVetoVotes = 0 + proposal.AbstainVotes = 0 + proposal.CurrentStatus = ProposalStatusOpen + + store(Proposals, , proposal) // Store proposal in Proposals mapping + return proposalID +``` + +### Deposit + +Once a proposal is submitted, if +`Proposal.TotalDeposit < ActiveParam.MinDeposit`, Atom holders can send +`MsgDeposit` transactions to increase the proposal's deposit. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L134-L147 +``` + +**State modifications:** + +* Decrease balance of sender by `deposit` +* Add `deposit` of sender in `proposal.Deposits` +* Increase `proposal.TotalDeposit` by sender's `deposit` +* If `MinDeposit` is reached: + * Push `proposalID` in `ProposalProcessingQueueEnd` +* Transfer `Deposit` from the `proposer` to the governance `ModuleAccount` + +A `MsgDeposit` transaction has to go through a number of checks to be valid. +These checks are outlined in the following pseudocode. + +```go +// PSEUDOCODE // +// Check if MsgDeposit is valid. If it is, increase deposit and check if MinDeposit is reached + +upon receiving txGovDeposit from sender do + // check if proposal is correctly formatted. Includes fee payment. + + if !correctlyFormatted(txGovDeposit) + throw + + proposal = load(Proposals, ) // proposal is a const key, proposalID is variable + + if (proposal == nil) + // There is no proposal for this proposalID + throw + + if (txGovDeposit.Deposit.Atoms <= 0) OR (sender.AtomBalance < txGovDeposit.Deposit.Atoms) OR (proposal.CurrentStatus != ProposalStatusOpen) + + // deposit is negative or null + // OR sender has insufficient funds + // OR proposal is not open for deposit anymore + + throw + + depositParam = load(GlobalParams, 'DepositParam') + + if (CurrentBlock >= proposal.SubmitBlock + depositParam.MaxDepositPeriod) + proposal.CurrentStatus = ProposalStatusClosed + + else + // sender can deposit + sender.AtomBalance -= txGovDeposit.Deposit.Atoms + + proposal.Deposits.append({txGovVote.Deposit, sender}) + proposal.TotalDeposit.Plus(txGovDeposit.Deposit) + + if (proposal.TotalDeposit >= depositParam.MinDeposit) + // MinDeposit is reached, vote opens + + proposal.VotingStartBlock = CurrentBlock + proposal.CurrentStatus = ProposalStatusActive + ProposalProcessingQueue.push(txGovDeposit.ProposalID) + + store(Proposals, , proposal) +``` + +### Vote + +Once `ActiveParam.MinDeposit` is reached, voting period starts. From there, +bonded Atom holders are able to send `MsgVote` transactions to cast their +vote on the proposal. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L92-L108 +``` + +**State modifications:** + +* Record `Vote` of sender + +:::note +Gas cost for this message has to take into account the future tallying of the vote in EndBlocker. +::: + +Next is a pseudocode outline of the way `MsgVote` transactions are handled: + +```go + // PSEUDOCODE // + // Check if MsgVote is valid. If it is, count vote// + + upon receiving txGovVote from sender do + // check if proposal is correctly formatted. Includes fee payment. + + if !correctlyFormatted(txGovDeposit) + throw + + proposal = load(Proposals, ) + + if (proposal == nil) + // There is no proposal for this proposalID + throw + + + if (proposal.CurrentStatus == ProposalStatusActive) + + + // Sender can vote if + // Proposal is active + // Sender has some bonds + + store(Governance, , txGovVote.Vote) // Voters can vote multiple times. Re-voting overrides previous vote. This is ok because tallying is done once at the end. +``` + +## Events + +The governance module emits the following events: + +### EndBlocker + +| Type | Attribute Key | Attribute Value | +|-------------------|-----------------|------------------| +| inactive_proposal | proposal_id | {proposalID} | +| inactive_proposal | proposal_result | {proposalResult} | +| active_proposal | proposal_id | {proposalID} | +| active_proposal | proposal_result | {proposalResult} | + +### Handlers + +#### MsgSubmitProposal + +| Type | Attribute Key | Attribute Value | +|---------------------|---------------------|-----------------| +| submit_proposal | proposal_id | {proposalID} | +| submit_proposal [0] | voting_period_start | {proposalID} | +| proposal_deposit | amount | {depositAmount} | +| proposal_deposit | proposal_id | {proposalID} | +| message | module | governance | +| message | action | submit_proposal | +| message | sender | {senderAddress} | + +* [0] Event only emitted if the voting period starts during the submission. + +#### MsgVote + +| Type | Attribute Key | Attribute Value | +|---------------|---------------|-----------------| +| proposal_vote | option | {voteOption} | +| proposal_vote | proposal_id | {proposalID} | +| message | module | governance | +| message | action | vote | +| message | sender | {senderAddress} | + +#### MsgVoteWeighted + +| Type | Attribute Key | Attribute Value | +|---------------|---------------|-----------------------| +| proposal_vote | option | {weightedVoteOptions} | +| proposal_vote | proposal_id | {proposalID} | +| message | module | governance | +| message | action | vote | +| message | sender | {senderAddress} | + +#### MsgDeposit + +| Type | Attribute Key | Attribute Value | +|----------------------|---------------------|-----------------| +| proposal_deposit | amount | {depositAmount} | +| proposal_deposit | proposal_id | {proposalID} | +| proposal_deposit [0] | voting_period_start | {proposalID} | +| message | module | governance | +| message | action | deposit | +| message | sender | {senderAddress} | + +* [0] Event only emitted if the voting period starts during the submission. + +## Parameters + +The governance module contains the following parameters: + +| Key | Type | Example | +|-------------------------------|------------------|-----------------------------------------| +| min_deposit | array (coins) | [{"denom":"uatom","amount":"10000000"}] | +| max_deposit_period | string (time ns) | "172800000000000" (17280s) | +| voting_period | string (time ns) | "172800000000000" (17280s) | +| quorum | string (dec) | "0.334000000000000000" | +| threshold | string (dec) | "0.500000000000000000" | +| veto | string (dec) | "0.334000000000000000" | +| expedited_threshold | string (time ns) | "0.667000000000000000" | +| expedited_voting_period | string (time ns) | "86400000000000" (8600s) | +| expedited_min_deposit | array (coins) | [{"denom":"uatom","amount":"50000000"}] | +| burn_proposal_deposit_prevote | bool | false | +| burn_vote_quorum | bool | false | +| burn_vote_veto | bool | true | + +**NOTE**: The governance module contains parameters that are objects unlike other +modules. If only a subset of parameters are desired to be changed, only they need +to be included and not the entire parameter object structure. + +## Client + +### CLI + +A user can query and interact with the `gov` module using the CLI. + +#### Query + +The `query` commands allow users to query `gov` state. + +```bash +simd query gov --help +``` + +##### deposit + +The `deposit` command allows users to query a deposit for a given proposal from a given depositor. + +```bash +simd query gov deposit [proposal-id] [depositer-addr] [flags] +``` + +Example: + +```bash +simd query gov deposit 1 cosmos1.. +``` + +Example Output: + +```bash +amount: +- amount: "100" + denom: stake +depositor: cosmos1.. +proposal_id: "1" +``` + +##### deposits + +The `deposits` command allows users to query all deposits for a given proposal. + +```bash +simd query gov deposits [proposal-id] [flags] +``` + +Example: + +```bash +simd query gov deposits 1 +``` + +Example Output: + +```bash +deposits: +- amount: + - amount: "100" + denom: stake + depositor: cosmos1.. + proposal_id: "1" +pagination: + next_key: null + total: "0" +``` + +##### param + +The `param` command allows users to query a given parameter for the `gov` module. + +```bash +simd query gov param [param-type] [flags] +``` + +Example: + +```bash +simd query gov param voting +``` + +Example Output: + +```bash +voting_period: "172800000000000" +``` + +##### params + +The `params` command allows users to query all parameters for the `gov` module. + +```bash +simd query gov params [flags] +``` + +Example: + +```bash +simd query gov params +``` + +Example Output: + +```bash +deposit_params: + max_deposit_period: 172800s + min_deposit: + - amount: "10000000" + denom: stake +params: + expedited_min_deposit: + - amount: "50000000" + denom: stake + expedited_threshold: "0.670000000000000000" + expedited_voting_period: 86400s + max_deposit_period: 172800s + min_deposit: + - amount: "10000000" + denom: stake + min_initial_deposit_ratio: "0.000000000000000000" + proposal_cancel_burn_rate: "0.500000000000000000" + quorum: "0.334000000000000000" + threshold: "0.500000000000000000" + veto_threshold: "0.334000000000000000" + voting_period: 172800s +tally_params: + quorum: "0.334000000000000000" + threshold: "0.500000000000000000" + veto_threshold: "0.334000000000000000" +voting_params: + voting_period: 172800s +``` + +##### proposal + +The `proposal` command allows users to query a given proposal. + +```bash +simd query gov proposal [proposal-id] [flags] +``` + +Example: + +```bash +simd query gov proposal 1 +``` + +Example Output: + +```bash +deposit_end_time: "2022-03-30T11:50:20.819676256Z" +final_tally_result: + abstain_count: "0" + no_count: "0" + no_with_veto_count: "0" + yes_count: "0" +id: "1" +messages: +- '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "10" + denom: stake + from_address: cosmos1.. + to_address: cosmos1.. +metadata: AQ== +status: PROPOSAL_STATUS_DEPOSIT_PERIOD +submit_time: "2022-03-28T11:50:20.819676256Z" +total_deposit: +- amount: "10" + denom: stake +voting_end_time: null +voting_start_time: null +``` + +##### proposals + +The `proposals` command allows users to query all proposals with optional filters. + +```bash +simd query gov proposals [flags] +``` + +Example: + +```bash +simd query gov proposals +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +proposals: +- deposit_end_time: "2022-03-30T11:50:20.819676256Z" + final_tally_result: + abstain_count: "0" + no_count: "0" + no_with_veto_count: "0" + yes_count: "0" + id: "1" + messages: + - '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "10" + denom: stake + from_address: cosmos1.. + to_address: cosmos1.. + metadata: AQ== + status: PROPOSAL_STATUS_DEPOSIT_PERIOD + submit_time: "2022-03-28T11:50:20.819676256Z" + total_deposit: + - amount: "10" + denom: stake + voting_end_time: null + voting_start_time: null +- deposit_end_time: "2022-03-30T14:02:41.165025015Z" + final_tally_result: + abstain_count: "0" + no_count: "0" + no_with_veto_count: "0" + yes_count: "0" + id: "2" + messages: + - '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "10" + denom: stake + from_address: cosmos1.. + to_address: cosmos1.. + metadata: AQ== + status: PROPOSAL_STATUS_DEPOSIT_PERIOD + submit_time: "2022-03-28T14:02:41.165025015Z" + total_deposit: + - amount: "10" + denom: stake + voting_end_time: null + voting_start_time: null +``` + +##### proposer + +The `proposer` command allows users to query the proposer for a given proposal. + +```bash +simd query gov proposer [proposal-id] [flags] +``` + +Example: + +```bash +simd query gov proposer 1 +``` + +Example Output: + +```bash +proposal_id: "1" +proposer: cosmos1.. +``` + +##### tally + +The `tally` command allows users to query the tally of a given proposal vote. + +```bash +simd query gov tally [proposal-id] [flags] +``` + +Example: + +```bash +simd query gov tally 1 +``` + +Example Output: + +```bash +abstain: "0" +"no": "0" +no_with_veto: "0" +"yes": "1" +``` + +##### vote + +The `vote` command allows users to query a vote for a given proposal. + +```bash +simd query gov vote [proposal-id] [voter-addr] [flags] +``` + +Example: + +```bash +simd query gov vote 1 cosmos1.. +``` + +Example Output: + +```bash +option: VOTE_OPTION_YES +options: +- option: VOTE_OPTION_YES + weight: "1.000000000000000000" +proposal_id: "1" +voter: cosmos1.. +``` + +##### votes + +The `votes` command allows users to query all votes for a given proposal. + +```bash +simd query gov votes [proposal-id] [flags] +``` + +Example: + +```bash +simd query gov votes 1 +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +votes: +- option: VOTE_OPTION_YES + options: + - option: VOTE_OPTION_YES + weight: "1.000000000000000000" + proposal_id: "1" + voter: cosmos1.. +``` + +#### Transactions + +The `tx` commands allow users to interact with the `gov` module. + +```bash +simd tx gov --help +``` + +##### deposit + +The `deposit` command allows users to deposit tokens for a given proposal. + +```bash +simd tx gov deposit [proposal-id] [deposit] [flags] +``` + +Example: + +```bash +simd tx gov deposit 1 10000000stake --from cosmos1.. +``` + +##### draft-proposal + +The `draft-proposal` command allows users to draft any type of proposal. +The command returns a `draft_proposal.json`, to be used by `submit-proposal` after being completed. +The `draft_metadata.json` is meant to be uploaded to [IPFS](#metadata). + +```bash +simd tx gov draft-proposal +``` + +##### submit-proposal + +The `submit-proposal` command allows users to submit a governance proposal along with some messages and metadata. +Messages, metadata and deposit are defined in a JSON file. + +```bash +simd tx gov submit-proposal [path-to-proposal-json] [flags] +``` + +Example: + +```bash +simd tx gov submit-proposal /path/to/proposal.json --from cosmos1.. +``` + +where `proposal.json` contains: + +```json +{ + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1...", // The gov module module address + "to_address": "cosmos1...", + "amount":[{"denom": "stake","amount": "10"}] + } + ], + "metadata": "AQ==", + "deposit": "10stake", + "title": "Proposal Title", + "summary": "Proposal Summary" +} +``` + +:::note +By default the metadata, summary and title are both limited by 255 characters, this can be overridden by the application developer. +::: + +##### submit-legacy-proposal + +The `submit-legacy-proposal` command allows users to submit a governance legacy proposal along with an initial deposit. + +```bash +simd tx gov submit-legacy-proposal [command] [flags] +``` + +Example: + +```bash +simd tx gov submit-legacy-proposal --title="Test Proposal" --description="testing" --type="Text" --deposit="100000000stake" --from cosmos1.. +``` + +Example (`param-change`): + +```bash +simd tx gov submit-legacy-proposal param-change proposal.json --from cosmos1.. +``` + +```json +{ + "title": "Test Proposal", + "description": "testing, testing, 1, 2, 3", + "changes": [ + { + "subspace": "staking", + "key": "MaxValidators", + "value": 100 + } + ], + "deposit": "10000000stake" +} +``` + +#### cancel-proposal + +Once proposal is canceled, from the deposits of proposal `deposits * proposal_cancel_ratio` will be burned or sent to `ProposalCancelDest` address , if `ProposalCancelDest` is empty then deposits will be burned. The `remaining deposits` will be sent to depositers. + +```bash +simd tx gov cancel-proposal [proposal-id] [flags] +``` + +Example: + +```bash +simd tx gov cancel-proposal 1 --from cosmos1... +``` + +##### vote + +The `vote` command allows users to submit a vote for a given governance proposal. + +```bash +simd tx gov vote [command] [flags] +``` + +Example: + +```bash +simd tx gov vote 1 yes --from cosmos1.. +``` + +##### weighted-vote + +The `weighted-vote` command allows users to submit a weighted vote for a given governance proposal. + +```bash +simd tx gov weighted-vote [proposal-id] [weighted-options] [flags] +``` + +Example: + +```bash +simd tx gov weighted-vote 1 yes=0.5,no=0.5 --from cosmos1.. +``` + +### gRPC + +A user can query the `gov` module using gRPC endpoints. + +#### Proposal + +The `Proposal` endpoint allows users to query a given proposal. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Proposal +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Proposal +``` + +Example Output: + +```bash +{ + "proposal": { + "proposalId": "1", + "content": {"@type":"/cosmos.gov.v1beta1.TextProposal","description":"testing, testing, 1, 2, 3","title":"Test Proposal"}, + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "finalTallyResult": { + "yes": "0", + "abstain": "0", + "no": "0", + "noWithVeto": "0" + }, + "submitTime": "2021-09-16T19:40:08.712440474Z", + "depositEndTime": "2021-09-18T19:40:08.712440474Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10000000" + } + ], + "votingStartTime": "2021-09-16T19:40:08.712440474Z", + "votingEndTime": "2021-09-18T19:40:08.712440474Z", + "title": "Test Proposal", + "summary": "testing, testing, 1, 2, 3" + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Proposal +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Proposal +``` + +Example Output: + +```bash +{ + "proposal": { + "id": "1", + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} + ], + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "finalTallyResult": { + "yesCount": "0", + "abstainCount": "0", + "noCount": "0", + "noWithVetoCount": "0" + }, + "submitTime": "2022-03-28T11:50:20.819676256Z", + "depositEndTime": "2022-03-30T11:50:20.819676256Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10000000" + } + ], + "votingStartTime": "2022-03-28T14:25:26.644857113Z", + "votingEndTime": "2022-03-30T14:25:26.644857113Z", + "metadata": "AQ==", + "title": "Test Proposal", + "summary": "testing, testing, 1, 2, 3" + } +} +``` + +#### Proposals + +The `Proposals` endpoint allows users to query all proposals with optional filters. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Proposals +``` + +Example: + +```bash +grpcurl -plaintext \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Proposals +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "proposalId": "1", + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "finalTallyResult": { + "yes": "0", + "abstain": "0", + "no": "0", + "noWithVeto": "0" + }, + "submitTime": "2022-03-28T11:50:20.819676256Z", + "depositEndTime": "2022-03-30T11:50:20.819676256Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10000000010" + } + ], + "votingStartTime": "2022-03-28T14:25:26.644857113Z", + "votingEndTime": "2022-03-30T14:25:26.644857113Z" + }, + { + "proposalId": "2", + "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", + "finalTallyResult": { + "yes": "0", + "abstain": "0", + "no": "0", + "noWithVeto": "0" + }, + "submitTime": "2022-03-28T14:02:41.165025015Z", + "depositEndTime": "2022-03-30T14:02:41.165025015Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10" + } + ], + "votingStartTime": "0001-01-01T00:00:00Z", + "votingEndTime": "0001-01-01T00:00:00Z" + } + ], + "pagination": { + "total": "2" + } +} + +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Proposals +``` + +Example: + +```bash +grpcurl -plaintext \ + localhost:9090 \ + cosmos.gov.v1.Query/Proposals +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "id": "1", + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} + ], + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "finalTallyResult": { + "yesCount": "0", + "abstainCount": "0", + "noCount": "0", + "noWithVetoCount": "0" + }, + "submitTime": "2022-03-28T11:50:20.819676256Z", + "depositEndTime": "2022-03-30T11:50:20.819676256Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10000000010" + } + ], + "votingStartTime": "2022-03-28T14:25:26.644857113Z", + "votingEndTime": "2022-03-30T14:25:26.644857113Z", + "metadata": "AQ==", + "title": "Proposal Title", + "summary": "Proposal Summary" + }, + { + "id": "2", + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} + ], + "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", + "finalTallyResult": { + "yesCount": "0", + "abstainCount": "0", + "noCount": "0", + "noWithVetoCount": "0" + }, + "submitTime": "2022-03-28T14:02:41.165025015Z", + "depositEndTime": "2022-03-30T14:02:41.165025015Z", + "totalDeposit": [ + { + "denom": "stake", + "amount": "10" + } + ], + "metadata": "AQ==", + "title": "Proposal Title", + "summary": "Proposal Summary" + } + ], + "pagination": { + "total": "2" + } +} +``` + +#### Vote + +The `Vote` endpoint allows users to query a vote for a given proposal. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Vote +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1","voter":"cosmos1.."}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Vote +``` + +Example Output: + +```bash +{ + "vote": { + "proposalId": "1", + "voter": "cosmos1..", + "option": "VOTE_OPTION_YES", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1000000000000000000" + } + ] + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Vote +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1","voter":"cosmos1.."}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Vote +``` + +Example Output: + +```bash +{ + "vote": { + "proposalId": "1", + "voter": "cosmos1..", + "option": "VOTE_OPTION_YES", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ] + } +} +``` + +#### Votes + +The `Votes` endpoint allows users to query all votes for a given proposal. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Votes +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Votes +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposalId": "1", + "voter": "cosmos1..", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1000000000000000000" + } + ] + } + ], + "pagination": { + "total": "1" + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Votes +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Votes +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposalId": "1", + "voter": "cosmos1..", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ] + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### Params + +The `Params` endpoint allows users to query all parameters for the `gov` module. + + + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Params +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"params_type":"voting"}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Params +``` + +Example Output: + +```bash +{ + "votingParams": { + "votingPeriod": "172800s" + }, + "depositParams": { + "maxDepositPeriod": "0s" + }, + "tallyParams": { + "quorum": "MA==", + "threshold": "MA==", + "vetoThreshold": "MA==" + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Params +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"params_type":"voting"}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Params +``` + +Example Output: + +```bash +{ + "votingParams": { + "votingPeriod": "172800s" + } +} +``` + +#### Deposit + +The `Deposit` endpoint allows users to query a deposit for a given proposal from a given depositor. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Deposit +``` + +Example: + +```bash +grpcurl -plaintext \ + '{"proposal_id":"1","depositor":"cosmos1.."}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Deposit +``` + +Example Output: + +```bash +{ + "deposit": { + "proposalId": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Deposit +``` + +Example: + +```bash +grpcurl -plaintext \ + '{"proposal_id":"1","depositor":"cosmos1.."}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Deposit +``` + +Example Output: + +```bash +{ + "deposit": { + "proposalId": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } +} +``` + +#### deposits + +The `Deposits` endpoint allows users to query all deposits for a given proposal. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/Deposits +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/Deposits +``` + +Example Output: + +```bash +{ + "deposits": [ + { + "proposalId": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } + ], + "pagination": { + "total": "1" + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/Deposits +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1.Query/Deposits +``` + +Example Output: + +```bash +{ + "deposits": [ + { + "proposalId": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### TallyResult + +The `TallyResult` endpoint allows users to query the tally of a given proposal. + +Using legacy v1beta1: + +```bash +cosmos.gov.v1beta1.Query/TallyResult +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1beta1.Query/TallyResult +``` + +Example Output: + +```bash +{ + "tally": { + "yes": "1000000", + "abstain": "0", + "no": "0", + "noWithVeto": "0" + } +} +``` + +Using v1: + +```bash +cosmos.gov.v1.Query/TallyResult +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ + localhost:9090 \ + cosmos.gov.v1.Query/TallyResult +``` + +Example Output: + +```bash +{ + "tally": { + "yes": "1000000", + "abstain": "0", + "no": "0", + "noWithVeto": "0" + } +} +``` + +### REST + +A user can query the `gov` module using REST endpoints. + +#### proposal + +The `proposals` endpoint allows users to query a given proposal. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1 +``` + +Example Output: + +```bash +{ + "proposal": { + "proposal_id": "1", + "content": null, + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "final_tally_result": { + "yes": "0", + "abstain": "0", + "no": "0", + "no_with_veto": "0" + }, + "submit_time": "2022-03-28T11:50:20.819676256Z", + "deposit_end_time": "2022-03-30T11:50:20.819676256Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10000000010" + } + ], + "voting_start_time": "2022-03-28T14:25:26.644857113Z", + "voting_end_time": "2022-03-30T14:25:26.644857113Z" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1 +``` + +Example Output: + +```bash +{ + "proposal": { + "id": "1", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1..", + "to_address": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10" + } + ] + } + ], + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "final_tally_result": { + "yes_count": "0", + "abstain_count": "0", + "no_count": "0", + "no_with_veto_count": "0" + }, + "submit_time": "2022-03-28T11:50:20.819676256Z", + "deposit_end_time": "2022-03-30T11:50:20.819676256Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10000000" + } + ], + "voting_start_time": "2022-03-28T14:25:26.644857113Z", + "voting_end_time": "2022-03-30T14:25:26.644857113Z", + "metadata": "AQ==", + "title": "Proposal Title", + "summary": "Proposal Summary" + } +} +``` + +#### proposals + +The `proposals` endpoint also allows users to query all proposals with optional filters. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "proposal_id": "1", + "content": null, + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "final_tally_result": { + "yes": "0", + "abstain": "0", + "no": "0", + "no_with_veto": "0" + }, + "submit_time": "2022-03-28T11:50:20.819676256Z", + "deposit_end_time": "2022-03-30T11:50:20.819676256Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10000000" + } + ], + "voting_start_time": "2022-03-28T14:25:26.644857113Z", + "voting_end_time": "2022-03-30T14:25:26.644857113Z" + }, + { + "proposal_id": "2", + "content": null, + "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", + "final_tally_result": { + "yes": "0", + "abstain": "0", + "no": "0", + "no_with_veto": "0" + }, + "submit_time": "2022-03-28T14:02:41.165025015Z", + "deposit_end_time": "2022-03-30T14:02:41.165025015Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10" + } + ], + "voting_start_time": "0001-01-01T00:00:00Z", + "voting_end_time": "0001-01-01T00:00:00Z" + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "id": "1", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1..", + "to_address": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10" + } + ] + } + ], + "status": "PROPOSAL_STATUS_VOTING_PERIOD", + "final_tally_result": { + "yes_count": "0", + "abstain_count": "0", + "no_count": "0", + "no_with_veto_count": "0" + }, + "submit_time": "2022-03-28T11:50:20.819676256Z", + "deposit_end_time": "2022-03-30T11:50:20.819676256Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10000000010" + } + ], + "voting_start_time": "2022-03-28T14:25:26.644857113Z", + "voting_end_time": "2022-03-30T14:25:26.644857113Z", + "metadata": "AQ==", + "title": "Proposal Title", + "summary": "Proposal Summary" + }, + { + "id": "2", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1..", + "to_address": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10" + } + ] + } + ], + "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", + "final_tally_result": { + "yes_count": "0", + "abstain_count": "0", + "no_count": "0", + "no_with_veto_count": "0" + }, + "submit_time": "2022-03-28T14:02:41.165025015Z", + "deposit_end_time": "2022-03-30T14:02:41.165025015Z", + "total_deposit": [ + { + "denom": "stake", + "amount": "10" + } + ], + "voting_start_time": null, + "voting_end_time": null, + "metadata": "AQ==", + "title": "Proposal Title", + "summary": "Proposal Summary" + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +#### voter vote + +The `votes` endpoint allows users to query a vote for a given proposal. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes/cosmos1.. +``` + +Example Output: + +```bash +{ + "vote": { + "proposal_id": "1", + "voter": "cosmos1..", + "option": "VOTE_OPTION_YES", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ] + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id}/votes/{voter} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1/votes/cosmos1.. +``` + +Example Output: + +```bash +{ + "vote": { + "proposal_id": "1", + "voter": "cosmos1..", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ], + "metadata": "" + } +} +``` + +#### votes + +The `votes` endpoint allows users to query all votes for a given proposal. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id}/votes +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposal_id": "1", + "voter": "cosmos1..", + "option": "VOTE_OPTION_YES", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id}/votes +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1/votes +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposal_id": "1", + "voter": "cosmos1..", + "options": [ + { + "option": "VOTE_OPTION_YES", + "weight": "1.000000000000000000" + } + ], + "metadata": "" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### params + +The `params` endpoint allows users to query all parameters for the `gov` module. + + + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/params/{params_type} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/params/voting +``` + +Example Output: + +```bash +{ + "voting_params": { + "voting_period": "172800s" + }, + "deposit_params": { + "min_deposit": [ + ], + "max_deposit_period": "0s" + }, + "tally_params": { + "quorum": "0.000000000000000000", + "threshold": "0.000000000000000000", + "veto_threshold": "0.000000000000000000" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/params/{params_type} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/params/voting +``` + +Example Output: + +```bash +{ + "voting_params": { + "voting_period": "172800s" + }, + "deposit_params": { + "min_deposit": [ + ], + "max_deposit_period": "0s" + }, + "tally_params": { + "quorum": "0.000000000000000000", + "threshold": "0.000000000000000000", + "veto_threshold": "0.000000000000000000" + } +} +``` + +#### deposits + +The `deposits` endpoint allows users to query a deposit for a given proposal from a given depositor. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits/cosmos1.. +``` + +Example Output: + +```bash +{ + "deposit": { + "proposal_id": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id}/deposits/{depositor} +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1/deposits/cosmos1.. +``` + +Example Output: + +```bash +{ + "deposit": { + "proposal_id": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } +} +``` + +#### proposal deposits + +The `deposits` endpoint allows users to query all deposits for a given proposal. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits +``` + +Example Output: + +```bash +{ + "deposits": [ + { + "proposal_id": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id}/deposits +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1/deposits +``` + +Example Output: + +```bash +{ + "deposits": [ + { + "proposal_id": "1", + "depositor": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "10000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### tally + +The `tally` endpoint allows users to query the tally of a given proposal. + +Using legacy v1beta1: + +```bash +/cosmos/gov/v1beta1/proposals/{proposal_id}/tally +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1beta1/proposals/1/tally +``` + +Example Output: + +```bash +{ + "tally": { + "yes": "1000000", + "abstain": "0", + "no": "0", + "no_with_veto": "0" + } +} +``` + +Using v1: + +```bash +/cosmos/gov/v1/proposals/{proposal_id}/tally +``` + +Example: + +```bash +curl localhost:1317/cosmos/gov/v1/proposals/1/tally +``` + +Example Output: + +```bash +{ + "tally": { + "yes": "1000000", + "abstain": "0", + "no": "0", + "no_with_veto": "0" + } +} +``` + +## Metadata + +The gov module has two locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the gov and group modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure accross chains. + +### Proposal + +Location: off-chain as json object stored on IPFS (mirrors [group proposal](../group/README.md#metadata)) + +```json +{ + "title": "", + "authors": [""], + "summary": "", + "details": "", + "proposal_forum_url": "", + "vote_option_context": "", +} +``` + +:::note +The `authors` field is an array of strings, this is to allow for multiple authors to be listed in the metadata. +In v0.46, the `authors` field is a comma-separated string. Frontends are encouraged to support both formats for backwards compatibility. +::: + +### Vote + +Location: on-chain as json within 255 character limit (mirrors [group vote](../group/README.md#metadata)) + +```json +{ + "justification": "", +} +``` + +## Future Improvements + +The current documentation only describes the minimum viable product for the +governance module. Future improvements may include: + +* **`BountyProposals`:** If accepted, a `BountyProposal` creates an open + bounty. The `BountyProposal` specifies how many Atoms will be given upon + completion. These Atoms will be taken from the `reserve pool`. After a + `BountyProposal` is accepted by governance, anybody can submit a + `SoftwareUpgradeProposal` with the code to claim the bounty. Note that once a + `BountyProposal` is accepted, the corresponding funds in the `reserve pool` + are locked so that payment can always be honored. In order to link a + `SoftwareUpgradeProposal` to an open bounty, the submitter of the + `SoftwareUpgradeProposal` will use the `Proposal.LinkedProposal` attribute. + If a `SoftwareUpgradeProposal` linked to an open bounty is accepted by + governance, the funds that were reserved are automatically transferred to the + submitter. +* **Complex delegation:** Delegators could choose other representatives than + their validators. Ultimately, the chain of representatives would always end + up to a validator, but delegators could inherit the vote of their chosen + representative before they inherit the vote of their validator. In other + words, they would only inherit the vote of their validator if their other + appointed representative did not vote. +* **Better process for proposal review:** There would be two parts to + `proposal.Deposit`, one for anti-spam (same as in MVP) and an other one to + reward third party auditors. diff --git a/versioned_docs/version-0.47/integrate/modules/group/README.md b/versioned_docs/version-0.47/integrate/modules/group/README.md new file mode 100644 index 000000000..b94fec728 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/group/README.md @@ -0,0 +1,2156 @@ +--- +sidebar_position: 1 +--- + +# `x/group` + +## Abstract + +The following documents specify the group module. + +This module allows the creation and management of on-chain multisig accounts and enables voting for message execution based on configurable decision policies. + +## Contents + +* [Concepts](#concepts) + * [Group](#group) + * [Group Policy](#group-policy) + * [Decision Policy](#decision-policy) + * [Proposal](#proposal) + * [Pruning](#pruning) +* [State](#state) + * [Group Table](#group-table) + * [Group Member Table](#group-member-table) + * [Group Policy Table](#group-policy-table) + * [Proposal Table](#proposal-table) + * [Vote Table](#vote-table) +* [Msg Service](#msg-service) + * [Msg/CreateGroup](#msgcreategroup) + * [Msg/UpdateGroupMembers](#msgupdategroupmembers) + * [Msg/UpdateGroupAdmin](#msgupdategroupadmin) + * [Msg/UpdateGroupMetadata](#msgupdategroupmetadata) + * [Msg/CreateGroupPolicy](#msgcreategrouppolicy) + * [Msg/CreateGroupWithPolicy](#msgcreategroupwithpolicy) + * [Msg/UpdateGroupPolicyAdmin](#msgupdategrouppolicyadmin) + * [Msg/UpdateGroupPolicyDecisionPolicy](#msgupdategrouppolicydecisionpolicy) + * [Msg/UpdateGroupPolicyMetadata](#msgupdategrouppolicymetadata) + * [Msg/SubmitProposal](#msgsubmitproposal) + * [Msg/WithdrawProposal](#msgwithdrawproposal) + * [Msg/Vote](#msgvote) + * [Msg/Exec](#msgexec) + * [Msg/LeaveGroup](#msgleavegroup) +* [Events](#events) + * [EventCreateGroup](#eventcreategroup) + * [EventUpdateGroup](#eventupdategroup) + * [EventCreateGroupPolicy](#eventcreategrouppolicy) + * [EventUpdateGroupPolicy](#eventupdategrouppolicy) + * [EventCreateProposal](#eventcreateproposal) + * [EventWithdrawProposal](#eventwithdrawproposal) + * [EventVote](#eventvote) + * [EventExec](#eventexec) + * [EventLeaveGroup](#eventleavegroup) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) +* [Metadata](#metadata) + +## Concepts + +### Group + +A group is simply an aggregation of accounts with associated weights. It is not +an account and doesn't have a balance. It doesn't in and of itself have any +sort of voting or decision weight. It does have an "administrator" which has +the ability to add, remove and update members in the group. Note that a +group policy account could be an administrator of a group, and that the +administrator doesn't necessarily have to be a member of the group. + +### Group Policy + +A group policy is an account associated with a group and a decision policy. +Group policies are abstracted from groups because a single group may have +multiple decision policies for different types of actions. Managing group +membership separately from decision policies results in the least overhead +and keeps membership consistent across different policies. The pattern that +is recommended is to have a single master group policy for a given group, +and then to create separate group policies with different decision policies +and delegate the desired permissions from the master account to +those "sub-accounts" using the `x/authz` module. + +### Decision Policy + +A decision policy is the mechanism by which members of a group can vote on +proposals, as well as the rules that dictate whether a proposal should pass +or not based on its tally outcome. + +All decision policies generally would have a mininum execution period and a +maximum voting window. The minimum execution period is the minimum amount of time +that must pass after submission in order for a proposal to potentially be executed, and it may +be set to 0. The maximum voting window is the maximum time after submission that a proposal may +be voted on before it is tallied. + +The chain developer also defines an app-wide maximum execution period, which is +the maximum amount of time after a proposal's voting period end where users are +allowed to execute a proposal. + +The current group module comes shipped with two decision policies: threshold +and percentage. Any chain developer can extend upon these two, by creating +custom decision policies, as long as they adhere to the `DecisionPolicy` +interface: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/types.go#L27-L45 +``` + +#### Threshold decision policy + +A threshold decision policy defines a threshold of yes votes (based on a tally +of voter weights) that must be achieved in order for a proposal to pass. For +this decision policy, abstain and veto are simply treated as no's. + +This decision policy also has a VotingPeriod window and a MinExecutionPeriod +window. The former defines the duration after proposal submission where members +are allowed to vote, after which tallying is performed. The latter specifies +the minimum duration after proposal submission where the proposal can be +executed. If set to 0, then the proposal is allowed to be executed immediately +on submission (using the `TRY_EXEC` option). Obviously, MinExecutionPeriod +cannot be greater than VotingPeriod+MaxExecutionPeriod (where MaxExecution is +the app-defined duration that specifies the window after voting ended where a +proposal can be executed). + +#### Percentage decision policy + +A percentage decision policy is similar to a threshold decision policy, except +that the threshold is not defined as a constant weight, but as a percentage. +It's more suited for groups where the group members' weights can be updated, as +the percentage threshold stays the same, and doesn't depend on how those member +weights get updated. + +Same as the Threshold decision policy, the percentage decision policy has the +two VotingPeriod and MinExecutionPeriod parameters. + +### Proposal + +Any member(s) of a group can submit a proposal for a group policy account to decide upon. +A proposal consists of a set of messages that will be executed if the proposal +passes as well as any metadata associated with the proposal. + +#### Voting + +There are four choices to choose while voting - yes, no, abstain and veto. Not +all decision policies will take the four choices into account. Votes can contain some optional metadata. +In the current implementation, the voting window begins as soon as a proposal +is submitted, and the end is defined by the group policy's decision policy. + +#### Withdrawing Proposals + +Proposals can be withdrawn any time before the voting period end, either by the +admin of the group policy or by one of the proposers. Once withdrawn, it is +marked as `PROPOSAL_STATUS_WITHDRAWN`, and no more voting or execution is +allowed on it. + +#### Aborted Proposals + +If the group policy is updated during the voting period of the proposal, then +the proposal is marked as `PROPOSAL_STATUS_ABORTED`, and no more voting or +execution is allowed on it. This is because the group policy defines the rules +of proposal voting and execution, so if those rules change during the lifecycle +of a proposal, then the proposal should be marked as stale. + +#### Tallying + +Tallying is the counting of all votes on a proposal. It happens only once in +the lifecycle of a proposal, but can be triggered by two factors, whichever +happens first: + +* either someone tries to execute the proposal (see next section), which can + happen on a `Msg/Exec` transaction, or a `Msg/{SubmitProposal,Vote}` + transaction with the `Exec` field set. When a proposal execution is attempted, + a tally is done first to make sure the proposal passes. +* or on `EndBlock` when the proposal's voting period end just passed. + +If the tally result passes the decision policy's rules, then the proposal is +marked as `PROPOSAL_STATUS_ACCEPTED`, or else it is marked as +`PROPOSAL_STATUS_REJECTED`. In any case, no more voting is allowed anymore, and the tally +result is persisted to state in the proposal's `FinalTallyResult`. + +#### Executing Proposals + +Proposals are executed only when the tallying is done, and the group account's +decision policy allows the proposal to pass based on the tally outcome. They +are marked by the status `PROPOSAL_STATUS_ACCEPTED`. Execution must happen +before a duration of `MaxExecutionPeriod` (set by the chain developer) after +each proposal's voting period end. + +Proposals will not be automatically executed by the chain in this current design, +but rather a user must submit a `Msg/Exec` transaction to attempt to execute the +proposal based on the current votes and decision policy. Any user (not only the +group members) can execute proposals that have been accepted, and execution fees are +paid by the proposal executor. +It's also possible to try to execute a proposal immediately on creation or on +new votes using the `Exec` field of `Msg/SubmitProposal` and `Msg/Vote` requests. +In the former case, proposers signatures are considered as yes votes. +In these cases, if the proposal can't be executed (i.e. it didn't pass the +decision policy's rules), it will still be opened for new votes and +could be tallied and executed later on. + +A successful proposal execution will have its `ExecutorResult` marked as +`PROPOSAL_EXECUTOR_RESULT_SUCCESS`. The proposal will be automatically pruned +after execution. On the other hand, a failed proposal execution will be marked +as `PROPOSAL_EXECUTOR_RESULT_FAILURE`. Such a proposal can be re-executed +multiple times, until it expires after `MaxExecutionPeriod` after voting period +end. + +### Pruning + +Proposals and votes are automatically pruned to avoid state bloat. + +Votes are pruned: + +* either after a successful tally, i.e. a tally whose result passes the decision + policy's rules, which can be trigged by a `Msg/Exec` or a + `Msg/{SubmitProposal,Vote}` with the `Exec` field set, +* or on `EndBlock` right after the proposal's voting period end. This applies to proposals with status `aborted` or `withdrawn` too. + +whichever happens first. + +Proposals are pruned: + +* on `EndBlock` whose proposal status is `withdrawn` or `aborted` on proposal's voting period end before tallying, +* and either after a successful proposal execution, +* or on `EndBlock` right after the proposal's `voting_period_end` + + `max_execution_period` (defined as an app-wide configuration) is passed, + +whichever happens first. + +## State + +The `group` module uses the `orm` package which provides table storage with support for +primary keys and secondary indexes. `orm` also defines `Sequence` which is a persistent unique key generator based on a counter that can be used along with `Table`s. + +Here's the list of tables and associated sequences and indexes stored as part of the `group` module. + +### Group Table + +The `groupTable` stores `GroupInfo`: `0x0 | BigEndian(GroupId) -> ProtocolBuffer(GroupInfo)`. + +#### groupSeq + +The value of `groupSeq` is incremented when creating a new group and corresponds to the new `GroupId`: `0x1 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +#### groupByAdminIndex + +`groupByAdminIndex` allows to retrieve groups by admin address: +`0x2 | len([]byte(group.Admin)) | []byte(group.Admin) | BigEndian(GroupId) -> []byte()`. + +### Group Member Table + +The `groupMemberTable` stores `GroupMember`s: `0x10 | BigEndian(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember)`. + +The `groupMemberTable` is a primary key table and its `PrimaryKey` is given by +`BigEndian(GroupId) | []byte(member.Address)` which is used by the following indexes. + +#### groupMemberByGroupIndex + +`groupMemberByGroupIndex` allows to retrieve group members by group id: +`0x11 | BigEndian(GroupId) | PrimaryKey -> []byte()`. + +#### groupMemberByMemberIndex + +`groupMemberByMemberIndex` allows to retrieve group members by member address: +`0x12 | len([]byte(member.Address)) | []byte(member.Address) | PrimaryKey -> []byte()`. + +### Group Policy Table + +The `groupPolicyTable` stores `GroupPolicyInfo`: `0x20 | len([]byte(Address)) | []byte(Address) -> ProtocolBuffer(GroupPolicyInfo)`. + +The `groupPolicyTable` is a primary key table and its `PrimaryKey` is given by +`len([]byte(Address)) | []byte(Address)` which is used by the following indexes. + +#### groupPolicySeq + +The value of `groupPolicySeq` is incremented when creating a new group policy and is used to generate the new group policy account `Address`: +`0x21 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +#### groupPolicyByGroupIndex + +`groupPolicyByGroupIndex` allows to retrieve group policies by group id: +`0x22 | BigEndian(GroupId) | PrimaryKey -> []byte()`. + +#### groupPolicyByAdminIndex + +`groupPolicyByAdminIndex` allows to retrieve group policies by admin address: +`0x23 | len([]byte(Address)) | []byte(Address) | PrimaryKey -> []byte()`. + +### Proposal Table + +The `proposalTable` stores `Proposal`s: `0x30 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal)`. + +#### proposalSeq + +The value of `proposalSeq` is incremented when creating a new proposal and corresponds to the new `ProposalId`: `0x31 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +#### proposalByGroupPolicyIndex + +`proposalByGroupPolicyIndex` allows to retrieve proposals by group policy account address: +`0x32 | len([]byte(account.Address)) | []byte(account.Address) | BigEndian(ProposalId) -> []byte()`. + +#### ProposalsByVotingPeriodEndIndex + +`proposalsByVotingPeriodEndIndex` allows to retrieve proposals sorted by chronological `voting_period_end`: +`0x33 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte()`. + +This index is used when tallying the proposal votes at the end of the voting period, and for pruning proposals at `VotingPeriodEnd + MaxExecutionPeriod`. + +### Vote Table + +The `voteTable` stores `Vote`s: `0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote)`. + +The `voteTable` is a primary key table and its `PrimaryKey` is given by +`BigEndian(ProposalId) | []byte(voter.Address)` which is used by the following indexes. + +#### voteByProposalIndex + +`voteByProposalIndex` allows to retrieve votes by proposal id: +`0x41 | BigEndian(ProposalId) | PrimaryKey -> []byte()`. + +#### voteByVoterIndex + +`voteByVoterIndex` allows to retrieve votes by voter address: +`0x42 | len([]byte(voter.Address)) | []byte(voter.Address) | PrimaryKey -> []byte()`. + +## Msg Service + +### Msg/CreateGroup + +A new group can be created with the `MsgCreateGroup`, which has an admin address, a list of members and some optional metadata. + +The metadata has a maximum length that is chosen by the app developer, and +passed into the group keeper as a config. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L67-L80 +``` + +It's expected to fail if + +* metadata length is greater than `MaxMetadataLen` config +* members are not correctly set (e.g. wrong address format, duplicates, or with 0 weight). + +### Msg/UpdateGroupMembers + +Group members can be updated with the `UpdateGroupMembers`. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L88-L102 +``` + +In the list of `MemberUpdates`, an existing member can be removed by setting its weight to 0. + +It's expected to fail if: + +* the signer is not the admin of the group. +* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group. + +### Msg/UpdateGroupAdmin + +The `UpdateGroupAdmin` can be used to update a group admin. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L107-L120 +``` + +It's expected to fail if the signer is not the admin of the group. + +### Msg/UpdateGroupMetadata + +The `UpdateGroupMetadata` can be used to update a group metadata. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L125-L138 +``` + +It's expected to fail if: + +* new metadata length is greater than `MaxMetadataLen` config. +* the signer is not the admin of the group. + +### Msg/CreateGroupPolicy + +A new group policy can be created with the `MsgCreateGroupPolicy`, which has an admin address, a group id, a decision policy and some optional metadata. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L147-L165 +``` + +It's expected to fail if: + +* the signer is not the admin of the group. +* metadata length is greater than `MaxMetadataLen` config. +* the decision policy's `Validate()` method doesn't pass against the group. + +### Msg/CreateGroupWithPolicy + +A new group with policy can be created with the `MsgCreateGroupWithPolicy`, which has an admin address, a list of members, a decision policy, a `group_policy_as_admin` field to optionally set group and group policy admin with group policy address and some optional metadata for group and group policy. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L191-L215 +``` + +It's expected to fail for the same reasons as `Msg/CreateGroup` and `Msg/CreateGroupPolicy`. + +### Msg/UpdateGroupPolicyAdmin + +The `UpdateGroupPolicyAdmin` can be used to update a group policy admin. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L173-L186 +``` + +It's expected to fail if the signer is not the admin of the group policy. + +### Msg/UpdateGroupPolicyDecisionPolicy + +The `UpdateGroupPolicyDecisionPolicy` can be used to update a decision policy. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L226-L241 +``` + +It's expected to fail if: + +* the signer is not the admin of the group policy. +* the new decision policy's `Validate()` method doesn't pass against the group. + +### Msg/UpdateGroupPolicyMetadata + +The `UpdateGroupPolicyMetadata` can be used to update a group policy metadata. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L246-L259 +``` + +It's expected to fail if: + +* new metadata length is greater than `MaxMetadataLen` config. +* the signer is not the admin of the group. + +### Msg/SubmitProposal + +A new proposal can be created with the `MsgSubmitProposal`, which has a group policy account address, a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata. +An optional `Exec` value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L281-L315 +``` + +It's expected to fail if: + +* metadata, title, or summary length is greater than `MaxMetadataLen` config. +* if any of the proposers is not a group member. + +### Msg/WithdrawProposal + +A proposal can be withdrawn using `MsgWithdrawProposal` which has an `address` (can be either a proposer or the group policy admin) and a `proposal_id` (which has to be withdrawn). + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L323-L333 +``` + +It's expected to fail if: + +* the signer is neither the group policy admin nor proposer of the proposal. +* the proposal is already closed or aborted. + +### Msg/Vote + +A new vote can be created with the `MsgVote`, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata. +An optional `Exec` value can be provided to try to execute the proposal immediately after voting. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L338-L358 +``` + +It's expected to fail if: + +* metadata length is greater than `MaxMetadataLen` config. +* the proposal is not in voting period anymore. + +### Msg/Exec + +A proposal can be executed with the `MsgExec`. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L363-L373 +``` + +The messages that are part of this proposal won't be executed if: + +* the proposal has not been accepted by the group policy. +* the proposal has already been successfully executed. + +### Msg/LeaveGroup + +The `MsgLeaveGroup` allows group member to leave a group. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/group/v1/tx.proto#L381-L391 +``` + +It's expected to fail if: + +* the group member is not part of the group. +* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group. + +## Events + +The group module emits the following events: + +### EventCreateGroup + +| Type | Attribute Key | Attribute Value | +| -------------------------------- | ------------- | -------------------------------- | +| message | action | /cosmos.group.v1.Msg/CreateGroup | +| cosmos.group.v1.EventCreateGroup | group_id | {groupId} | + +### EventUpdateGroup + +| Type | Attribute Key | Attribute Value | +| -------------------------------- | ------------- | ---------------------------------------------------------- | +| message | action | /cosmos.group.v1.Msg/UpdateGroup{Admin\|Metadata\|Members} | +| cosmos.group.v1.EventUpdateGroup | group_id | {groupId} | + +### EventCreateGroupPolicy + +| Type | Attribute Key | Attribute Value | +| -------------------------------------- | ------------- | -------------------------------------- | +| message | action | /cosmos.group.v1.Msg/CreateGroupPolicy | +| cosmos.group.v1.EventCreateGroupPolicy | address | {groupPolicyAddress} | + +### EventUpdateGroupPolicy + +| Type | Attribute Key | Attribute Value | +| -------------------------------------- | ------------- | ----------------------------------------------------------------------- | +| message | action | /cosmos.group.v1.Msg/UpdateGroupPolicy{Admin\|Metadata\|DecisionPolicy} | +| cosmos.group.v1.EventUpdateGroupPolicy | address | {groupPolicyAddress} | + +### EventCreateProposal + +| Type | Attribute Key | Attribute Value | +| ----------------------------------- | ------------- | ----------------------------------- | +| message | action | /cosmos.group.v1.Msg/CreateProposal | +| cosmos.group.v1.EventCreateProposal | proposal_id | {proposalId} | + +### EventWithdrawProposal + +| Type | Attribute Key | Attribute Value | +| ------------------------------------- | ------------- | ------------------------------------- | +| message | action | /cosmos.group.v1.Msg/WithdrawProposal | +| cosmos.group.v1.EventWithdrawProposal | proposal_id | {proposalId} | + +### EventVote + +| Type | Attribute Key | Attribute Value | +| ------------------------- | ------------- | ------------------------- | +| message | action | /cosmos.group.v1.Msg/Vote | +| cosmos.group.v1.EventVote | proposal_id | {proposalId} | + +## EventExec + +| Type | Attribute Key | Attribute Value | +| ------------------------- | ------------- | ------------------------- | +| message | action | /cosmos.group.v1.Msg/Exec | +| cosmos.group.v1.EventExec | proposal_id | {proposalId} | +| cosmos.group.v1.EventExec | logs | {logs_string} | + +### EventLeaveGroup + +| Type | Attribute Key | Attribute Value | +| ------------------------------- | ------------- | ------------------------------- | +| message | action | /cosmos.group.v1.Msg/LeaveGroup | +| cosmos.group.v1.EventLeaveGroup | proposal_id | {proposalId} | +| cosmos.group.v1.EventLeaveGroup | address | {address} | + + +## Client + +### CLI + +A user can query and interact with the `group` module using the CLI. + +#### Query + +The `query` commands allow users to query `group` state. + +```bash +simd query group --help +``` + +##### group-info + +The `group-info` command allows users to query for group info by given group id. + +```bash +simd query group group-info [id] [flags] +``` + +Example: + +```bash +simd query group group-info 1 +``` + +Example Output: + +```bash +admin: cosmos1.. +group_id: "1" +metadata: AQ== +total_weight: "3" +version: "1" +``` + +##### group-policy-info + +The `group-policy-info` command allows users to query for group policy info by account address of group policy . + +```bash +simd query group group-policy-info [group-policy-account] [flags] +``` + +Example: + +```bash +simd query group group-policy-info cosmos1.. +``` + +Example Output: + +```bash +address: cosmos1.. +admin: cosmos1.. +decision_policy: + '@type': /cosmos.group.v1.ThresholdDecisionPolicy + threshold: "1" + windows: + min_execution_period: 0s + voting_period: 432000s +group_id: "1" +metadata: AQ== +version: "1" +``` + +##### group-members + +The `group-members` command allows users to query for group members by group id with pagination flags. + +```bash +simd query group group-members [id] [flags] +``` + +Example: + +```bash +simd query group group-members 1 +``` + +Example Output: + +```bash +members: +- group_id: "1" + member: + address: cosmos1.. + metadata: AQ== + weight: "2" +- group_id: "1" + member: + address: cosmos1.. + metadata: AQ== + weight: "1" +pagination: + next_key: null + total: "2" +``` + +##### groups-by-admin + +The `groups-by-admin` command allows users to query for groups by admin account address with pagination flags. + +```bash +simd query group groups-by-admin [admin] [flags] +``` + +Example: + +```bash +simd query group groups-by-admin cosmos1.. +``` + +Example Output: + +```bash +groups: +- admin: cosmos1.. + group_id: "1" + metadata: AQ== + total_weight: "3" + version: "1" +- admin: cosmos1.. + group_id: "2" + metadata: AQ== + total_weight: "3" + version: "1" +pagination: + next_key: null + total: "2" +``` + +##### group-policies-by-group + +The `group-policies-by-group` command allows users to query for group policies by group id with pagination flags. + +```bash +simd query group group-policies-by-group [group-id] [flags] +``` + +Example: + +```bash +simd query group group-policies-by-group 1 +``` + +Example Output: + +```bash +group_policies: +- address: cosmos1.. + admin: cosmos1.. + decision_policy: + '@type': /cosmos.group.v1.ThresholdDecisionPolicy + threshold: "1" + windows: + min_execution_period: 0s + voting_period: 432000s + group_id: "1" + metadata: AQ== + version: "1" +- address: cosmos1.. + admin: cosmos1.. + decision_policy: + '@type': /cosmos.group.v1.ThresholdDecisionPolicy + threshold: "1" + windows: + min_execution_period: 0s + voting_period: 432000s + group_id: "1" + metadata: AQ== + version: "1" +pagination: + next_key: null + total: "2" +``` + +##### group-policies-by-admin + +The `group-policies-by-admin` command allows users to query for group policies by admin account address with pagination flags. + +```bash +simd query group group-policies-by-admin [admin] [flags] +``` + +Example: + +```bash +simd query group group-policies-by-admin cosmos1.. +``` + +Example Output: + +```bash +group_policies: +- address: cosmos1.. + admin: cosmos1.. + decision_policy: + '@type': /cosmos.group.v1.ThresholdDecisionPolicy + threshold: "1" + windows: + min_execution_period: 0s + voting_period: 432000s + group_id: "1" + metadata: AQ== + version: "1" +- address: cosmos1.. + admin: cosmos1.. + decision_policy: + '@type': /cosmos.group.v1.ThresholdDecisionPolicy + threshold: "1" + windows: + min_execution_period: 0s + voting_period: 432000s + group_id: "1" + metadata: AQ== + version: "1" +pagination: + next_key: null + total: "2" +``` + +##### proposal + +The `proposal` command allows users to query for proposal by id. + +```bash +simd query group proposal [id] [flags] +``` + +Example: + +```bash +simd query group proposal 1 +``` + +Example Output: + +```bash +proposal: + address: cosmos1.. + executor_result: EXECUTOR_RESULT_NOT_RUN + group_policy_version: "1" + group_version: "1" + metadata: AQ== + msgs: + - '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "100000000" + denom: stake + from_address: cosmos1.. + to_address: cosmos1.. + proposal_id: "1" + proposers: + - cosmos1.. + result: RESULT_UNFINALIZED + status: STATUS_SUBMITTED + submitted_at: "2021-12-17T07:06:26.310638964Z" + windows: + min_execution_period: 0s + voting_period: 432000s + vote_state: + abstain_count: "0" + no_count: "0" + veto_count: "0" + yes_count: "0" + summary: "Summary" + title: "Title" +``` + +##### proposals-by-group-policy + +The `proposals-by-group-policy` command allows users to query for proposals by account address of group policy with pagination flags. + +```bash +simd query group proposals-by-group-policy [group-policy-account] [flags] +``` + +Example: + +```bash +simd query group proposals-by-group-policy cosmos1.. +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "1" +proposals: +- address: cosmos1.. + executor_result: EXECUTOR_RESULT_NOT_RUN + group_policy_version: "1" + group_version: "1" + metadata: AQ== + msgs: + - '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "100000000" + denom: stake + from_address: cosmos1.. + to_address: cosmos1.. + proposal_id: "1" + proposers: + - cosmos1.. + result: RESULT_UNFINALIZED + status: STATUS_SUBMITTED + submitted_at: "2021-12-17T07:06:26.310638964Z" + windows: + min_execution_period: 0s + voting_period: 432000s + vote_state: + abstain_count: "0" + no_count: "0" + veto_count: "0" + yes_count: "0" + summary: "Summary" + title: "Title" +``` + +##### vote + +The `vote` command allows users to query for vote by proposal id and voter account address. + +```bash +simd query group vote [proposal-id] [voter] [flags] +``` + +Example: + +```bash +simd query group vote 1 cosmos1.. +``` + +Example Output: + +```bash +vote: + choice: CHOICE_YES + metadata: AQ== + proposal_id: "1" + submitted_at: "2021-12-17T08:05:02.490164009Z" + voter: cosmos1.. +``` + +##### votes-by-proposal + +The `votes-by-proposal` command allows users to query for votes by proposal id with pagination flags. + +```bash +simd query group votes-by-proposal [proposal-id] [flags] +``` + +Example: + +```bash +simd query group votes-by-proposal 1 +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "1" +votes: +- choice: CHOICE_YES + metadata: AQ== + proposal_id: "1" + submitted_at: "2021-12-17T08:05:02.490164009Z" + voter: cosmos1.. +``` + +##### votes-by-voter + +The `votes-by-voter` command allows users to query for votes by voter account address with pagination flags. + +```bash +simd query group votes-by-voter [voter] [flags] +``` + +Example: + +```bash +simd query group votes-by-voter cosmos1.. +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "1" +votes: +- choice: CHOICE_YES + metadata: AQ== + proposal_id: "1" + submitted_at: "2021-12-17T08:05:02.490164009Z" + voter: cosmos1.. +``` + +### Transactions + +The `tx` commands allow users to interact with the `group` module. + +```bash +simd tx group --help +``` + +#### create-group + +The `create-group` command allows users to create a group which is an aggregation of member accounts with associated weights and +an administrator account. + +```bash +simd tx group create-group [admin] [metadata] [members-json-file] +``` + +Example: + +```bash +simd tx group create-group cosmos1.. "AQ==" members.json +``` + +#### update-group-admin + +The `update-group-admin` command allows users to update a group's admin. + +```bash +simd tx group update-group-admin [admin] [group-id] [new-admin] [flags] +``` + +Example: + +```bash +simd tx group update-group-admin cosmos1.. 1 cosmos1.. +``` + +#### update-group-members + +The `update-group-members` command allows users to update a group's members. + +```bash +simd tx group update-group-members [admin] [group-id] [members-json-file] [flags] +``` + +Example: + +```bash +simd tx group update-group-members cosmos1.. 1 members.json +``` + +#### update-group-metadata + +The `update-group-metadata` command allows users to update a group's metadata. + +```bash +simd tx group update-group-metadata [admin] [group-id] [metadata] [flags] +``` + +Example: + +```bash +simd tx group update-group-metadata cosmos1.. 1 "AQ==" +``` + +#### create-group-policy + +The `create-group-policy` command allows users to create a group policy which is an account associated with a group and a decision policy. + +```bash +simd tx group create-group-policy [admin] [group-id] [metadata] [decision-policy] [flags] +``` + +Example: + +```bash +simd tx group create-group-policy cosmos1.. 1 "AQ==" '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}' +``` + +#### create-group-with-policy + +The `create-group-with-policy` command allows users to create a group which is an aggregation of member accounts with associated weights and an administrator account with decision policy. If the `--group-policy-as-admin` flag is set to `true`, the group policy address becomes the group and group policy admin. + +```bash +simd tx group create-group-with-policy [admin] [group-metadata] [group-policy-metadata] [members-json-file] [decision-policy] [flags] +``` + +Example: + +```bash +simd tx group create-group-with-policy cosmos1.. "AQ==" "AQ==" members.json '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}' +``` + +#### update-group-policy-admin + +The `update-group-policy-admin` command allows users to update a group policy admin. + +```bash +simd tx group update-group-policy-admin [admin] [group-policy-account] [new-admin] [flags] +``` + +Example: + +```bash +simd tx group update-group-policy-admin cosmos1.. cosmos1.. cosmos1.. +``` + +#### update-group-policy-metadata + +The `update-group-policy-metadata` command allows users to update a group policy metadata. + +```bash +simd tx group update-group-policy-metadata [admin] [group-policy-account] [new-metadata] [flags] +``` + +Example: + +```bash +simd tx group update-group-policy-metadata cosmos1.. cosmos1.. "AQ==" +``` + +#### update-group-policy-decision-policy + +The `update-group-policy-decision-policy` command allows users to update a group policy's decision policy. + +```bash +simd tx group update-group-policy-decision-policy [admin] [group-policy-account] [decision-policy] [flags] +``` + +Example: + +```bash +simd tx group update-group-policy-decision-policy cosmos1.. cosmos1.. '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"2", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}' +``` + +#### create-proposal + +The `create-proposal` command allows users to submit a new proposal. + +```bash +simd tx group create-proposal [group-policy-account] [proposer[,proposer]*] [msg_tx_json_file] [metadata] [flags] +``` + +Example: + +```bash +simd tx group create-proposal cosmos1.. cosmos1.. msg_tx.json "AQ==" +``` + +#### withdraw-proposal + +The `withdraw-proposal` command allows users to withdraw a proposal. + +```bash +simd tx group withdraw-proposal [proposal-id] [group-policy-admin-or-proposer] +``` + +Example: + +```bash +simd tx group withdraw-proposal 1 cosmos1.. +``` + +#### vote + +The `vote` command allows users to vote on a proposal. + +```bash +simd tx group vote proposal-id] [voter] [choice] [metadata] [flags] +``` + +Example: + +```bash +simd tx group vote 1 cosmos1.. CHOICE_YES "AQ==" +``` + +#### exec + +The `exec` command allows users to execute a proposal. + +```bash +simd tx group exec [proposal-id] [flags] +``` + +Example: + +```bash +simd tx group exec 1 +``` + +#### leave-group + +The `leave-group` command allows group member to leave the group. + +```bash +simd tx group leave-group [member-address] [group-id] +``` + +Example: + +```bash +simd tx group leave-group cosmos1... 1 +``` + +### gRPC + +A user can query the `group` module using gRPC endpoints. + +#### GroupInfo + +The `GroupInfo` endpoint allows users to query for group info by given group id. + +```bash +cosmos.group.v1.Query/GroupInfo +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"group_id":1}' localhost:9090 cosmos.group.v1.Query/GroupInfo +``` + +Example Output: + +```bash +{ + "info": { + "groupId": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "totalWeight": "3" + } +} +``` + +#### GroupPolicyInfo + +The `GroupPolicyInfo` endpoint allows users to query for group policy info by account address of group policy. + +```bash +cosmos.group.v1.Query/GroupPolicyInfo +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPolicyInfo +``` + +Example Output: + +```bash +{ + "info": { + "address": "cosmos1..", + "groupId": "1", + "admin": "cosmos1..", + "version": "1", + "decisionPolicy": {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows": {"voting_period": "120h", "min_execution_period": "0s"}}, + } +} +``` + +#### GroupMembers + +The `GroupMembers` endpoint allows users to query for group members by group id with pagination flags. + +```bash +cosmos.group.v1.Query/GroupMembers +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupMembers +``` + +Example Output: + +```bash +{ + "members": [ + { + "groupId": "1", + "member": { + "address": "cosmos1..", + "weight": "1" + } + }, + { + "groupId": "1", + "member": { + "address": "cosmos1..", + "weight": "2" + } + } + ], + "pagination": { + "total": "2" + } +} +``` + +#### GroupsByAdmin + +The `GroupsByAdmin` endpoint allows users to query for groups by admin account address with pagination flags. + +```bash +cosmos.group.v1.Query/GroupsByAdmin +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupsByAdmin +``` + +Example Output: + +```bash +{ + "groups": [ + { + "groupId": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "totalWeight": "3" + }, + { + "groupId": "2", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "totalWeight": "3" + } + ], + "pagination": { + "total": "2" + } +} +``` + +#### GroupPoliciesByGroup + +The `GroupPoliciesByGroup` endpoint allows users to query for group policies by group id with pagination flags. + +```bash +cosmos.group.v1.Query/GroupPoliciesByGroup +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByGroup +``` + +Example Output: + +```bash +{ + "GroupPolicies": [ + { + "address": "cosmos1..", + "groupId": "1", + "admin": "cosmos1..", + "version": "1", + "decisionPolicy": {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}}, + }, + { + "address": "cosmos1..", + "groupId": "1", + "admin": "cosmos1..", + "version": "1", + "decisionPolicy": {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}}, + } + ], + "pagination": { + "total": "2" + } +} +``` + +#### GroupPoliciesByAdmin + +The `GroupPoliciesByAdmin` endpoint allows users to query for group policies by admin account address with pagination flags. + +```bash +cosmos.group.v1.Query/GroupPoliciesByAdmin +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByAdmin +``` + +Example Output: + +```bash +{ + "GroupPolicies": [ + { + "address": "cosmos1..", + "groupId": "1", + "admin": "cosmos1..", + "version": "1", + "decisionPolicy": {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}}, + }, + { + "address": "cosmos1..", + "groupId": "1", + "admin": "cosmos1..", + "version": "1", + "decisionPolicy": {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}}, + } + ], + "pagination": { + "total": "2" + } +} +``` + +#### Proposal + +The `Proposal` endpoint allows users to query for proposal by id. + +```bash +cosmos.group.v1.Query/Proposal +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/Proposal +``` + +Example Output: + +```bash +{ + "proposal": { + "proposalId": "1", + "address": "cosmos1..", + "proposers": [ + "cosmos1.." + ], + "submittedAt": "2021-12-17T07:06:26.310638964Z", + "groupVersion": "1", + "GroupPolicyVersion": "1", + "status": "STATUS_SUBMITTED", + "result": "RESULT_UNFINALIZED", + "voteState": { + "yesCount": "0", + "noCount": "0", + "abstainCount": "0", + "vetoCount": "0" + }, + "windows": { + "min_execution_period": "0s", + "voting_period": "432000s" + }, + "executorResult": "EXECUTOR_RESULT_NOT_RUN", + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"100000000"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} + ], + "title": "Title", + "summary": "Summary", + } +} +``` + +#### ProposalsByGroupPolicy + +The `ProposalsByGroupPolicy` endpoint allows users to query for proposals by account address of group policy with pagination flags. + +```bash +cosmos.group.v1.Query/ProposalsByGroupPolicy +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/ProposalsByGroupPolicy +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "proposalId": "1", + "address": "cosmos1..", + "proposers": [ + "cosmos1.." + ], + "submittedAt": "2021-12-17T08:03:27.099649352Z", + "groupVersion": "1", + "GroupPolicyVersion": "1", + "status": "STATUS_CLOSED", + "result": "RESULT_ACCEPTED", + "voteState": { + "yesCount": "1", + "noCount": "0", + "abstainCount": "0", + "vetoCount": "0" + }, + "windows": { + "min_execution_period": "0s", + "voting_period": "432000s" + }, + "executorResult": "EXECUTOR_RESULT_NOT_RUN", + "messages": [ + {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"100000000"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} + ], + "title": "Title", + "summary": "Summary", + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### VoteByProposalVoter + +The `VoteByProposalVoter` endpoint allows users to query for vote by proposal id and voter account address. + +```bash +cosmos.group.v1.Query/VoteByProposalVoter +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1","voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VoteByProposalVoter +``` + +Example Output: + +```bash +{ + "vote": { + "proposalId": "1", + "voter": "cosmos1..", + "choice": "CHOICE_YES", + "submittedAt": "2021-12-17T08:05:02.490164009Z" + } +} +``` + +#### VotesByProposal + +The `VotesByProposal` endpoint allows users to query for votes by proposal id with pagination flags. + +```bash +cosmos.group.v1.Query/VotesByProposal +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/VotesByProposal +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposalId": "1", + "voter": "cosmos1..", + "choice": "CHOICE_YES", + "submittedAt": "2021-12-17T08:05:02.490164009Z" + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### VotesByVoter + +The `VotesByVoter` endpoint allows users to query for votes by voter account address with pagination flags. + +```bash +cosmos.group.v1.Query/VotesByVoter +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VotesByVoter +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposalId": "1", + "voter": "cosmos1..", + "choice": "CHOICE_YES", + "submittedAt": "2021-12-17T08:05:02.490164009Z" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### REST + +A user can query the `group` module using REST endpoints. + +#### GroupInfo + +The `GroupInfo` endpoint allows users to query for group info by given group id. + +```bash +/cosmos/group/v1/group_info/{group_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/group_info/1 +``` + +Example Output: + +```bash +{ + "info": { + "id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "total_weight": "3" + } +} +``` + +#### GroupPolicyInfo + +The `GroupPolicyInfo` endpoint allows users to query for group policy info by account address of group policy. + +```bash +/cosmos/group/v1/group_policy_info/{address} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/group_policy_info/cosmos1.. +``` + +Example Output: + +```bash +{ + "info": { + "address": "cosmos1..", + "group_id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "decision_policy": { + "@type": "/cosmos.group.v1.ThresholdDecisionPolicy", + "threshold": "1", + "windows": { + "voting_period": "120h", + "min_execution_period": "0s" + } + }, + } +} +``` + +#### GroupMembers + +The `GroupMembers` endpoint allows users to query for group members by group id with pagination flags. + +```bash +/cosmos/group/v1/group_members/{group_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/group_members/1 +``` + +Example Output: + +```bash +{ + "members": [ + { + "group_id": "1", + "member": { + "address": "cosmos1..", + "weight": "1", + "metadata": "AQ==" + } + }, + { + "group_id": "1", + "member": { + "address": "cosmos1..", + "weight": "2", + "metadata": "AQ==" + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +#### GroupsByAdmin + +The `GroupsByAdmin` endpoint allows users to query for groups by admin account address with pagination flags. + +```bash +/cosmos/group/v1/groups_by_admin/{admin} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/groups_by_admin/cosmos1.. +``` + +Example Output: + +```bash +{ + "groups": [ + { + "id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "total_weight": "3" + }, + { + "id": "2", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "total_weight": "3" + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +#### GroupPoliciesByGroup + +The `GroupPoliciesByGroup` endpoint allows users to query for group policies by group id with pagination flags. + +```bash +/cosmos/group/v1/group_policies_by_group/{group_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/group_policies_by_group/1 +``` + +Example Output: + +```bash +{ + "group_policies": [ + { + "address": "cosmos1..", + "group_id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "decision_policy": { + "@type": "/cosmos.group.v1.ThresholdDecisionPolicy", + "threshold": "1", + "windows": { + "voting_period": "120h", + "min_execution_period": "0s" + } + }, + }, + { + "address": "cosmos1..", + "group_id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "decision_policy": { + "@type": "/cosmos.group.v1.ThresholdDecisionPolicy", + "threshold": "1", + "windows": { + "voting_period": "120h", + "min_execution_period": "0s" + } + }, + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +#### GroupPoliciesByAdmin + +The `GroupPoliciesByAdmin` endpoint allows users to query for group policies by admin account address with pagination flags. + +```bash +/cosmos/group/v1/group_policies_by_admin/{admin} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/group_policies_by_admin/cosmos1.. +``` + +Example Output: + +```bash +{ + "group_policies": [ + { + "address": "cosmos1..", + "group_id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "decision_policy": { + "@type": "/cosmos.group.v1.ThresholdDecisionPolicy", + "threshold": "1", + "windows": { + "voting_period": "120h", + "min_execution_period": "0s" + } + }, + }, + { + "address": "cosmos1..", + "group_id": "1", + "admin": "cosmos1..", + "metadata": "AQ==", + "version": "1", + "decision_policy": { + "@type": "/cosmos.group.v1.ThresholdDecisionPolicy", + "threshold": "1", + "windows": { + "voting_period": "120h", + "min_execution_period": "0s" + } + }, + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +``` + +#### Proposal + +The `Proposal` endpoint allows users to query for proposal by id. + +```bash +/cosmos/group/v1/proposal/{proposal_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/proposal/1 +``` + +Example Output: + +```bash +{ + "proposal": { + "proposal_id": "1", + "address": "cosmos1..", + "metadata": "AQ==", + "proposers": [ + "cosmos1.." + ], + "submitted_at": "2021-12-17T07:06:26.310638964Z", + "group_version": "1", + "group_policy_version": "1", + "status": "STATUS_SUBMITTED", + "result": "RESULT_UNFINALIZED", + "vote_state": { + "yes_count": "0", + "no_count": "0", + "abstain_count": "0", + "veto_count": "0" + }, + "windows": { + "min_execution_period": "0s", + "voting_period": "432000s" + }, + "executor_result": "EXECUTOR_RESULT_NOT_RUN", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1..", + "to_address": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "100000000" + } + ] + } + ], + "title": "Title", + "summary": "Summary", + } +} +``` + +#### ProposalsByGroupPolicy + +The `ProposalsByGroupPolicy` endpoint allows users to query for proposals by account address of group policy with pagination flags. + +```bash +/cosmos/group/v1/proposals_by_group_policy/{address} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/proposals_by_group_policy/cosmos1.. +``` + +Example Output: + +```bash +{ + "proposals": [ + { + "id": "1", + "group_policy_address": "cosmos1..", + "metadata": "AQ==", + "proposers": [ + "cosmos1.." + ], + "submit_time": "2021-12-17T08:03:27.099649352Z", + "group_version": "1", + "group_policy_version": "1", + "status": "STATUS_CLOSED", + "result": "RESULT_ACCEPTED", + "vote_state": { + "yes_count": "1", + "no_count": "0", + "abstain_count": "0", + "veto_count": "0" + }, + "windows": { + "min_execution_period": "0s", + "voting_period": "432000s" + }, + "executor_result": "EXECUTOR_RESULT_NOT_RUN", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1..", + "to_address": "cosmos1..", + "amount": [ + { + "denom": "stake", + "amount": "100000000" + } + ] + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### VoteByProposalVoter + +The `VoteByProposalVoter` endpoint allows users to query for vote by proposal id and voter account address. + +```bash +/cosmos/group/v1/vote_by_proposal_voter/{proposal_id}/{voter} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1beta1/vote_by_proposal_voter/1/cosmos1.. +``` + +Example Output: + +```bash +{ + "vote": { + "proposal_id": "1", + "voter": "cosmos1..", + "choice": "CHOICE_YES", + "metadata": "AQ==", + "submitted_at": "2021-12-17T08:05:02.490164009Z" + } +} +``` + +#### VotesByProposal + +The `VotesByProposal` endpoint allows users to query for votes by proposal id with pagination flags. + +```bash +/cosmos/group/v1/votes_by_proposal/{proposal_id} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/votes_by_proposal/1 +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposal_id": "1", + "voter": "cosmos1..", + "option": "CHOICE_YES", + "metadata": "AQ==", + "submit_time": "2021-12-17T08:05:02.490164009Z" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### VotesByVoter + +The `VotesByVoter` endpoint allows users to query for votes by voter account address with pagination flags. + +```bash +/cosmos/group/v1/votes_by_voter/{voter} +``` + +Example: + +```bash +curl localhost:1317/cosmos/group/v1/votes_by_voter/cosmos1.. +``` + +Example Output: + +```bash +{ + "votes": [ + { + "proposal_id": "1", + "voter": "cosmos1..", + "choice": "CHOICE_YES", + "metadata": "AQ==", + "submitted_at": "2021-12-17T08:05:02.490164009Z" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +## Metadata + +The group module has four locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the group and gov modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure accross chains. + +### Proposal + +Location: off-chain as json object stored on IPFS (mirrors [gov proposal](../gov/README.md#metadata)) + +```json +{ + "title": "", + "authors": [""], + "summary": "", + "details": "", + "proposal_forum_url": "", + "vote_option_context": "", +} +``` + +:::note +The `authors` field is an array of strings, this is to allow for multiple authors to be listed in the metadata. +In v0.46, the `authors` field is a comma-separated string. Frontends are encouraged to support both formats for backwards compatibility. +::: + +### Vote + +Location: on-chain as json within 255 character limit (mirrors [gov vote](../gov/README.md#metadata)) + +```json +{ + "justification": "", +} +``` + +### Group + +Location: off-chain as json object stored on IPFS + +```json +{ + "name": "", + "description": "", + "group_website_url": "", + "group_forum_url": "", +} +``` + +### Decision policy + +Location: on-chain as json within 255 character limit + +```json +{ + "name": "", + "description": "", +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/mint/README.md b/versioned_docs/version-0.47/integrate/modules/mint/README.md new file mode 100644 index 000000000..900615bba --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/mint/README.md @@ -0,0 +1,383 @@ +--- +sidebar_position: 1 +--- + +# `x/mint` + +## Contents + +* [State](#state) + * [Minter](#minter) + * [Params](#params) +* [Begin-Block](#begin-block) + * [NextInflationRate](#nextinflationrate) + * [NextAnnualProvisions](#nextannualprovisions) + * [BlockProvision](#blockprovision) +* [Parameters](#parameters) +* [Events](#events) + * [BeginBlocker](#beginblocker) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) + +## Concepts + +### The Minting Mechanism + +The minting mechanism was designed to: + +* allow for a flexible inflation rate determined by market demand targeting a particular bonded-stake ratio +* effect a balance between market liquidity and staked supply + +In order to best determine the appropriate market rate for inflation rewards, a +moving change rate is used. The moving change rate mechanism ensures that if +the % bonded is either over or under the goal %-bonded, the inflation rate will +adjust to further incentivize or disincentivize being bonded, respectively. Setting the goal +%-bonded at less than 100% encourages the network to maintain some non-staked tokens +which should help provide some liquidity. + +It can be broken down in the following way: + +* If the inflation rate is below the goal %-bonded the inflation rate will + increase until a maximum value is reached +* If the goal % bonded (67% in Cosmos-Hub) is maintained, then the inflation + rate will stay constant +* If the inflation rate is above the goal %-bonded the inflation rate will + decrease until a minimum value is reached + + +## State + +### Minter + +The minter is a space for holding current inflation information. + +* Minter: `0x00 -> ProtocolBuffer(minter)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L10-L24 +``` + +### Params + +The mint module stores it's params in state with the prefix of `0x01`, +it can be updated with governance or the address with authority. + +* Params: `mint/params -> legacy_amino(params)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L26-L59 +``` + +## Begin-Block + +Minting parameters are recalculated and inflation paid at the beginning of each block. + +### Inflation rate calculation + +Inflation rate is calculated using an "inflation calculation function" that's +passed to the `NewAppModule` function. If no function is passed, then the SDK's +default inflation function will be used (`NextInflationRate`). In case a custom +inflation calculation logic is needed, this can be achieved by defining and +passing a function that matches `InflationCalculationFn`'s signature. + +```go +type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec +``` + +#### NextInflationRate + +The target annual inflation rate is recalculated each block. +The inflation is also subject to a rate change (positive or negative) +depending on the distance from the desired ratio (67%). The maximum rate change +possible is defined to be 13% per year, however the annual inflation is capped +as between 7% and 20%. + +```go +NextInflationRate(params Params, bondedRatio math.LegacyDec) (inflation math.LegacyDec) { + inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange + inflationRateChange = inflationRateChangePerYear/blocksPerYr + + // increase the new annual inflation for this next block + inflation += inflationRateChange + if inflation > params.InflationMax { + inflation = params.InflationMax + } + if inflation < params.InflationMin { + inflation = params.InflationMin + } + + return inflation +} +``` + +### NextAnnualProvisions + +Calculate the annual provisions based on current total supply and inflation +rate. This parameter is calculated once per block. + +```go +NextAnnualProvisions(params Params, totalSupply math.LegacyDec) (provisions math.LegacyDec) { + return Inflation * totalSupply +``` + +### BlockProvision + +Calculate the provisions generated for each block based on current annual provisions. The provisions are then minted by the `mint` module's `ModuleMinterAccount` and then transferred to the `auth`'s `FeeCollector` `ModuleAccount`. + +```go +BlockProvision(params Params) sdk.Coin { + provisionAmt = AnnualProvisions/ params.BlocksPerYear + return sdk.NewCoin(params.MintDenom, provisionAmt.Truncate()) +``` + + +## Parameters + +The minting module contains the following parameters: + +| Key | Type | Example | +|---------------------|-----------------|------------------------| +| MintDenom | string | "uatom" | +| InflationRateChange | string (dec) | "0.130000000000000000" | +| InflationMax | string (dec) | "0.200000000000000000" | +| InflationMin | string (dec) | "0.070000000000000000" | +| GoalBonded | string (dec) | "0.670000000000000000" | +| BlocksPerYear | string (uint64) | "6311520" | + + +## Events + +The minting module emits the following events: + +### BeginBlocker + +| Type | Attribute Key | Attribute Value | +|------|-------------------|--------------------| +| mint | bonded_ratio | {bondedRatio} | +| mint | inflation | {inflation} | +| mint | annual_provisions | {annualProvisions} | +| mint | amount | {amount} | + + +## Client + +### CLI + +A user can query and interact with the `mint` module using the CLI. + +#### Query + +The `query` commands allow users to query `mint` state. + +```shell +simd query mint --help +``` + +##### annual-provisions + +The `annual-provisions` command allow users to query the current minting annual provisions value + +```shell +simd query mint annual-provisions [flags] +``` + +Example: + +```shell +simd query mint annual-provisions +``` + +Example Output: + +```shell +22268504368893.612100895088410693 +``` + +##### inflation + +The `inflation` command allow users to query the current minting inflation value + +```shell +simd query mint inflation [flags] +``` + +Example: + +```shell +simd query mint inflation +``` + +Example Output: + +```shell +0.199200302563256955 +``` + +##### params + +The `params` command allow users to query the current minting parameters + +```shell +simd query mint params [flags] +``` + +Example: + +```yml +blocks_per_year: "4360000" +goal_bonded: "0.670000000000000000" +inflation_max: "0.200000000000000000" +inflation_min: "0.070000000000000000" +inflation_rate_change: "0.130000000000000000" +mint_denom: stake +``` + +### gRPC + +A user can query the `mint` module using gRPC endpoints. + +#### AnnualProvisions + +The `AnnualProvisions` endpoint allow users to query the current minting annual provisions value + +```shell +/cosmos.mint.v1beta1.Query/AnnualProvisions +``` + +Example: + +```shell +grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions +``` + +Example Output: + +```json +{ + "annualProvisions": "1432452520532626265712995618" +} +``` + +#### Inflation + +The `Inflation` endpoint allow users to query the current minting inflation value + +```shell +/cosmos.mint.v1beta1.Query/Inflation +``` + +Example: + +```shell +grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation +``` + +Example Output: + +```json +{ + "inflation": "130197115720711261" +} +``` + +#### Params + +The `Params` endpoint allow users to query the current minting parameters + +```shell +/cosmos.mint.v1beta1.Query/Params +``` + +Example: + +```shell +grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params +``` + +Example Output: + +```json +{ + "params": { + "mintDenom": "stake", + "inflationRateChange": "130000000000000000", + "inflationMax": "200000000000000000", + "inflationMin": "70000000000000000", + "goalBonded": "670000000000000000", + "blocksPerYear": "6311520" + } +} +``` + +### REST + +A user can query the `mint` module using REST endpoints. + +#### annual-provisions + +```shell +/cosmos/mint/v1beta1/annual_provisions +``` + +Example: + +```shell +curl "localhost:1317/cosmos/mint/v1beta1/annual_provisions" +``` + +Example Output: + +```json +{ + "annualProvisions": "1432452520532626265712995618" +} +``` + +#### inflation + +```shell +/cosmos/mint/v1beta1/inflation +``` + +Example: + +```shell +curl "localhost:1317/cosmos/mint/v1beta1/inflation" +``` + +Example Output: + +```json +{ + "inflation": "130197115720711261" +} +``` + +#### params + +```shell +/cosmos/mint/v1beta1/params +``` + +Example: + +```shell +curl "localhost:1317/cosmos/mint/v1beta1/params" +``` + +Example Output: + +```json +{ + "params": { + "mintDenom": "stake", + "inflationRateChange": "130000000000000000", + "inflationMax": "200000000000000000", + "inflationMin": "70000000000000000", + "goalBonded": "670000000000000000", + "blocksPerYear": "6311520" + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/nft/README.md b/versioned_docs/version-0.47/integrate/modules/nft/README.md new file mode 100644 index 000000000..34c1d4066 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/nft/README.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +--- + +# `x/nft` + +## Contents + +## Abstract + +`x/nft` is an implementation of a Cosmos SDK module, per [ADR 43](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-043-nft-module.md), that allows you to create nft classification, create nft, transfer nft, update nft, and support various queries by integrating the module. It is fully compatible with the ERC721 specification. + +* [Concepts](#concepts) + * [Class](#class) + * [NFT](#nft) +* [State](#state) + * [Class](#class-1) + * [NFT](#nft-1) + * [NFTOfClassByOwner](#nftofclassbyowner) + * [Owner](#owner) + * [TotalSupply](#totalsupply) +* [Messages](#messages) + * [MsgSend](#msgsend) +* [Events](#events) + +## Concepts + +### Class + +`x/nft` module defines a struct `Class` to describe the common characteristics of a class of nft, under this class, you can create a variety of nft, which is equivalent to an erc721 contract for Ethereum. The design is defined in the [ADR 043](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-043-nft-module.md). + +### NFT + +The full name of NFT is Non-Fungible Tokens. Because of the irreplaceable nature of NFT, it means that it can be used to represent unique things. The nft implemented by this module is fully compatible with Ethereum ERC721 standard. + +## State + +### Class + +Class is mainly composed of `id`, `name`, `symbol`, `description`, `uri`, `uri_hash`,`data` where `id` is the unique identifier of the class, similar to the Ethereum ERC721 contract address, the others are optional. + +* Class: `0x01 | classID | -> ProtocolBuffer(Class)` + +### NFT + +NFT is mainly composed of `class_id`, `id`, `uri`, `uri_hash` and `data`. Among them, `class_id` and `id` are two-tuples that identify the uniqueness of nft, `uri` and `uri_hash` is optional, which identifies the off-chain storage location of the nft, and `data` is an Any type. Use Any chain of `x/nft` modules can be customized by extending this field + +* NFT: `0x02 | classID | 0x00 | nftID |-> ProtocolBuffer(NFT)` + +### NFTOfClassByOwner + +NFTOfClassByOwner is mainly to realize the function of querying all nfts using classID and owner, without other redundant functions. + +* NFTOfClassByOwner: `0x03 | owner | 0x00 | classID | 0x00 | nftID |-> 0x01` + +### Owner + +Since there is no extra field in NFT to indicate the owner of nft, an additional key-value pair is used to save the ownership of nft. With the transfer of nft, the key-value pair is updated synchronously. + +* OwnerKey: `0x04 | classID | 0x00 | nftID |-> owner` + +### TotalSupply + +TotalSupply is responsible for tracking the number of all nfts under a certain class. Mint operation is performed under the changed class, supply increases by one, burn operation, and supply decreases by one. + +* OwnerKey: `0x05 | classID |-> totalSupply` + +## Messages + +In this section we describe the processing of messages for the NFT module. + +:::warning +The validation of `ClassID` and `NftID` is left to the app developer. +The SDK does not provide any validation for these fields. +::: + +### MsgSend + +You can use the `MsgSend` message to transfer the ownership of nft. This is a function provided by the `x/nft` module. Of course, you can use the `Transfer` method to implement your own transfer logic, but you need to pay extra attention to the transfer permissions. + +The message handling should fail if: + +* provided `ClassID` does not exist. +* provided `Id` does not exist. +* provided `Sender` does not the owner of nft. + +## Events + +The nft module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.nft.v1beta1). diff --git a/versioned_docs/version-0.47/integrate/modules/params/README.md b/versioned_docs/version-0.47/integrate/modules/params/README.md new file mode 100644 index 000000000..f8d374d0c --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/params/README.md @@ -0,0 +1,79 @@ +--- +sidebar_position: 1 +--- + +# `x/params` + +> Note: The Params module has been depreacted in favour of each module housing its own parameters. + +## Abstract + +Package params provides a globally available parameter store. + +There are two main types, Keeper and Subspace. Subspace is an isolated namespace for a +paramstore, where keys are prefixed by preconfigured spacename. Keeper has a +permission to access all existing spaces. + +Subspace can be used by the individual keepers, which need a private parameter store +that the other keepers cannot modify. The params Keeper can be used to add a route to `x/gov` router in order to modify any parameter in case a proposal passes. + +The following contents explains how to use params module for master and user modules. + +## Contents + +* [Keeper](#keeper) +* [Subspace](#subspace) + * [Key](#key) + * [KeyTable](#keytable) + * [ParamSet](#paramset) + +## Keeper + +In the app initialization stage, [subspaces](#subspace) can be allocated for other modules' keeper using `Keeper.Subspace` and are stored in `Keeper.spaces`. Then, those modules can have a reference to their specific parameter store through `Keeper.GetSubspace`. + +Example: + +```go +type ExampleKeeper struct { + paramSpace paramtypes.Subspace +} + +func (k ExampleKeeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSet(ctx, ¶ms) +} +``` + +## Subspace + +`Subspace` is a prefixed subspace of the parameter store. Each module which uses the +parameter store will take a `Subspace` to isolate permission to access. + +### Key + +Parameter keys are human readable alphanumeric strings. A parameter for the key +`"ExampleParameter"` is stored under `[]byte("SubspaceName" + "/" + "ExampleParameter")`, + where `"SubspaceName"` is the name of the subspace. + +Subkeys are secondary parameter keys those are used along with a primary parameter key. +Subkeys can be used for grouping or dynamic parameter key generation during runtime. + +### KeyTable + +All of the parameter keys that will be used should be registered at the compile +time. `KeyTable` is essentially a `map[string]attribute`, where the `string` is a parameter key. + +Currently, `attribute` consists of a `reflect.Type`, which indicates the parameter +type to check that provided key and value are compatible and registered, as well as a function `ValueValidatorFn` to validate values. + +Only primary keys have to be registered on the `KeyTable`. Subkeys inherit the +attribute of the primary key. + +### ParamSet + +Modules often define parameters as a proto message. The generated struct can implement +`ParamSet` interface to be used with the following methods: + +* `KeyTable.RegisterParamSet()`: registers all parameters in the struct +* `Subspace.{Get, Set}ParamSet()`: Get to & Set from the struct + +The implementor should be a pointer in order to use `GetParamSet()`. diff --git a/versioned_docs/version-0.47/integrate/modules/slashing/README.md b/versioned_docs/version-0.47/integrate/modules/slashing/README.md new file mode 100644 index 000000000..591a9a73a --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/slashing/README.md @@ -0,0 +1,813 @@ +--- +sidebar_position: 1 +--- + +# `x/slashing` + +## Abstract + +This section specifies the slashing module of the Cosmos SDK, which implements functionality +first outlined in the [Cosmos Whitepaper](https://cosmos.network/about/whitepaper) in June 2016. + +The slashing module enables Cosmos SDK-based blockchains to disincentivize any attributable action +by a protocol-recognized actor with value at stake by penalizing them ("slashing"). + +Penalties may include, but are not limited to: + +* Burning some amount of their stake +* Removing their ability to vote on future blocks for a period of time. + +This module will be used by the Cosmos Hub, the first hub in the Cosmos ecosystem. + +## Contents + +* [Concepts](#concepts) + * [States](#states) + * [Tombstone Caps](#tombstone-caps) + * [Infraction Timelines](#infraction-timelines) +* [State](#state) + * [Signing Info (Liveness)](#signing-info-liveness) + * [Params](#params) +* [Messages](#messages) + * [Unjail](#unjail) +* [BeginBlock](#beginblock) + * [Liveness Tracking](#liveness-tracking) +* [Hooks](#hooks) +* [Events](#events) +* [Staking Tombstone](#staking-tombstone) +* [Parameters](#parameters) +* [CLI](#cli) + * [Query](#query) + * [Transactions](#transactions) + * [gRPC](#grpc) + * [REST](#rest) + +## Concepts + +### States + +At any given time, there are any number of validators registered in the state +machine. Each block, the top `MaxValidators` (defined by `x/staking`) validators +who are not jailed become _bonded_, meaning that they may propose and vote on +blocks. Validators who are _bonded_ are _at stake_, meaning that part or all of +their stake and their delegators' stake is at risk if they commit a protocol fault. + +For each of these validators we keep a `ValidatorSigningInfo` record that contains +information partaining to validator's liveness and other infraction related +attributes. + +### Tombstone Caps + +In order to mitigate the impact of initially likely categories of non-malicious +protocol faults, the Cosmos Hub implements for each validator +a _tombstone_ cap, which only allows a validator to be slashed once for a double +sign fault. For example, if you misconfigure your HSM and double-sign a bunch of +old blocks, you'll only be punished for the first double-sign (and then immediately tombstombed). This will still be quite expensive and desirable to avoid, but tombstone caps +somewhat blunt the economic impact of unintentional misconfiguration. + +Liveness faults do not have caps, as they can't stack upon each other. Liveness bugs are "detected" as soon as the infraction occurs, and the validators are immediately put in jail, so it is not possible for them to commit multiple liveness faults without unjailing in between. + +### Infraction Timelines + +To illustrate how the `x/slashing` module handles submitted evidence through +CometBFT consensus, consider the following examples: + +**Definitions**: + +_[_ : timeline start +_]_ : timeline end +_Cn_ : infraction `n` committed +_Dn_ : infraction `n` discovered +_Vb_ : validator bonded +_Vu_ : validator unbonded + +#### Single Double Sign Infraction + +\[----------C1----D1,Vu-----\] + +A single infraction is committed then later discovered, at which point the +validator is unbonded and slashed at the full amount for the infraction. + +#### Multiple Double Sign Infractions + +\[----------C1--C2---C3---D1,D2,D3Vu-----\] + +Multiple infractions are committed and then later discovered, at which point the +validator is jailed and slashed for only one infraction. Because the validator +is also tombstoned, they can not rejoin the validator set. + +## State + +### Signing Info (Liveness) + +Every block includes a set of precommits by the validators for the previous block, +known as the `LastCommitInfo` provided by CometBFT. A `LastCommitInfo` is valid so +long as it contains precommits from +2/3 of total voting power. + +Proposers are incentivized to include precommits from all validators in the CometBFT `LastCommitInfo` +by receiving additional fees proportional to the difference between the voting +power included in the `LastCommitInfo` and +2/3 (see [fee distribution](../distribution/README.md#begin-block)). + +```go +type LastCommitInfo struct { + Round int32 + Votes []VoteInfo +} +``` + +Validators are penalized for failing to be included in the `LastCommitInfo` for some +number of blocks by being automatically jailed, potentially slashed, and unbonded. + +Information about validator's liveness activity is tracked through `ValidatorSigningInfo`. +It is indexed in the store as follows: + +* ValidatorSigningInfo: `0x01 | ConsAddrLen (1 byte) | ConsAddress -> ProtocolBuffer(ValSigningInfo)` +* MissedBlocksBitArray: `0x02 | ConsAddrLen (1 byte) | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format) + +The first mapping allows us to easily lookup the recent signing info for a +validator based on the validator's consensus address. + +The second mapping (`MissedBlocksBitArray`) acts +as a bit-array of size `SignedBlocksWindow` that tells us if the validator missed +the block for a given index in the bit-array. The index in the bit-array is given +as little endian uint64. +The result is a `varint` that takes on `0` or `1`, where `0` indicates the +validator did not miss (did sign) the corresponding block, and `1` indicates +they missed the block (did not sign). + +Note that the `MissedBlocksBitArray` is not explicitly initialized up-front. Keys +are added as we progress through the first `SignedBlocksWindow` blocks for a newly +bonded validator. The `SignedBlocksWindow` parameter defines the size +(number of blocks) of the sliding window used to track validator liveness. + +The information stored for tracking validator liveness is as follows: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/slashing/v1beta1/slashing.proto#L13-L35 +``` + +### Params + +The slashing module stores it's params in state with the prefix of `0x00`, +it can be updated with governance or the address with authority. + +* Params: `0x00 | ProtocolBuffer(Params)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/slashing/v1beta1/slashing.proto#L37-L59 +``` + +## Messages + +In this section we describe the processing of messages for the `slashing` module. + +### Unjail + +If a validator was automatically unbonded due to downtime and wishes to come back online & +possibly rejoin the bonded set, it must send `MsgUnjail`: + +```protobuf +// MsgUnjail is an sdk.Msg used for unjailing a jailed validator, thus returning +// them into the bonded validator set, so they can begin receiving provisions +// and rewards again. +message MsgUnjail { + string validator_addr = 1; +} +``` + +Below is a pseudocode of the `MsgSrv/Unjail` RPC: + +```go +unjail(tx MsgUnjail) + validator = getValidator(tx.ValidatorAddr) + if validator == nil + fail with "No validator found" + + if getSelfDelegation(validator) == 0 + fail with "validator must self delegate before unjailing" + + if !validator.Jailed + fail with "Validator not jailed, cannot unjail" + + info = GetValidatorSigningInfo(operator) + if info.Tombstoned + fail with "Tombstoned validator cannot be unjailed" + if block time < info.JailedUntil + fail with "Validator still jailed, cannot unjail until period has expired" + + validator.Jailed = false + setValidator(validator) + + return +``` + +If the validator has enough stake to be in the top `n = MaximumBondedValidators`, it will be automatically rebonded, +and all delegators still delegated to the validator will be rebonded and begin to again collect +provisions and rewards. + +## BeginBlock + +### Liveness Tracking + +At the beginning of each block, we update the `ValidatorSigningInfo` for each +validator and check if they've crossed below the liveness threshold over a +sliding window. This sliding window is defined by `SignedBlocksWindow` and the +index in this window is determined by `IndexOffset` found in the validator's +`ValidatorSigningInfo`. For each block processed, the `IndexOffset` is incremented +regardless if the validator signed or not. Once the index is determined, the +`MissedBlocksBitArray` and `MissedBlocksCounter` are updated accordingly. + +Finally, in order to determine if a validator crosses below the liveness threshold, +we fetch the maximum number of blocks missed, `maxMissed`, which is +`SignedBlocksWindow - (MinSignedPerWindow * SignedBlocksWindow)` and the minimum +height at which we can determine liveness, `minHeight`. If the current block is +greater than `minHeight` and the validator's `MissedBlocksCounter` is greater than +`maxMissed`, they will be slashed by `SlashFractionDowntime`, will be jailed +for `DowntimeJailDuration`, and have the following values reset: +`MissedBlocksBitArray`, `MissedBlocksCounter`, and `IndexOffset`. + +**Note**: Liveness slashes do **NOT** lead to a tombstombing. + +```go +height := block.Height + +for vote in block.LastCommitInfo.Votes { + signInfo := GetValidatorSigningInfo(vote.Validator.Address) + + // This is a relative index, so we counts blocks the validator SHOULD have + // signed. We use the 0-value default signing info if not present, except for + // start height. + index := signInfo.IndexOffset % SignedBlocksWindow() + signInfo.IndexOffset++ + + // Update MissedBlocksBitArray and MissedBlocksCounter. The MissedBlocksCounter + // just tracks the sum of MissedBlocksBitArray. That way we avoid needing to + // read/write the whole array each time. + missedPrevious := GetValidatorMissedBlockBitArray(vote.Validator.Address, index) + missed := !signed + + switch { + case !missedPrevious && missed: + // array index has changed from not missed to missed, increment counter + SetValidatorMissedBlockBitArray(vote.Validator.Address, index, true) + signInfo.MissedBlocksCounter++ + + case missedPrevious && !missed: + // array index has changed from missed to not missed, decrement counter + SetValidatorMissedBlockBitArray(vote.Validator.Address, index, false) + signInfo.MissedBlocksCounter-- + + default: + // array index at this index has not changed; no need to update counter + } + + if missed { + // emit events... + } + + minHeight := signInfo.StartHeight + SignedBlocksWindow() + maxMissed := SignedBlocksWindow() - MinSignedPerWindow() + + // If we are past the minimum height and the validator has missed too many + // jail and slash them. + if height > minHeight && signInfo.MissedBlocksCounter > maxMissed { + validator := ValidatorByConsAddr(vote.Validator.Address) + + // emit events... + + // We need to retrieve the stake distribution which signed the block, so we + // subtract ValidatorUpdateDelay from the block height, and subtract an + // additional 1 since this is the LastCommit. + // + // Note, that this CAN result in a negative "distributionHeight" up to + // -ValidatorUpdateDelay-1, i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block. + // That's fine since this is just used to filter unbonding delegations & redelegations. + distributionHeight := height - sdk.ValidatorUpdateDelay - 1 + + SlashWithInfractionReason(vote.Validator.Address, distributionHeight, vote.Validator.Power, SlashFractionDowntime(), stakingtypes.Downtime) + Jail(vote.Validator.Address) + + signInfo.JailedUntil = block.Time.Add(DowntimeJailDuration()) + + // We need to reset the counter & array so that the validator won't be + // immediately slashed for downtime upon rebonding. + signInfo.MissedBlocksCounter = 0 + signInfo.IndexOffset = 0 + ClearValidatorMissedBlockBitArray(vote.Validator.Address) + } + + SetValidatorSigningInfo(vote.Validator.Address, signInfo) +} +``` + +## Hooks + +This section contains a description of the module's `hooks`. Hooks are operations that are executed automatically when events are raised. + +### Staking hooks + +The slashing module implements the `StakingHooks` defined in `x/staking` and are used as record-keeping of validators information. During the app initialization, these hooks should be registered in the staking module struct. + +The following hooks impact the slashing state: + +* `AfterValidatorBonded` creates a `ValidatorSigningInfo` instance as described in the following section. +* `AfterValidatorCreated` stores a validator's consensus key. +* `AfterValidatorRemoved` removes a validator's consensus key. + +### Validator Bonded + +Upon successful first-time bonding of a new validator, we create a new `ValidatorSigningInfo` structure for the +now-bonded validator, which `StartHeight` of the current block. + +If the validator was out of the validator set and gets bonded again, its new bonded height is set. + +```go +onValidatorBonded(address sdk.ValAddress) + + signingInfo, found = GetValidatorSigningInfo(address) + if !found { + signingInfo = ValidatorSigningInfo { + StartHeight : CurrentHeight, + IndexOffset : 0, + JailedUntil : time.Unix(0, 0), + Tombstone : false, + MissedBloskCounter : 0 + } else { + signingInfo.StartHeight = CurrentHeight + } + + setValidatorSigningInfo(signingInfo) + } + + return +``` + +## Events + +The slashing module emits the following events: + +### MsgServer + +#### MsgUnjail + +| Type | Attribute Key | Attribute Value | +| ------- | ------------- | ------------------ | +| message | module | slashing | +| message | sender | {validatorAddress} | + +### Keeper + +### BeginBlocker: HandleValidatorSignature + +| Type | Attribute Key | Attribute Value | +| ----- | ------------- | --------------------------- | +| slash | address | {validatorConsensusAddress} | +| slash | power | {validatorPower} | +| slash | reason | {slashReason} | +| slash | jailed [0] | {validatorConsensusAddress} | +| slash | burned coins | {math.Int} | + +* [0] Only included if the validator is jailed. + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | --------------------------- | +| liveness | address | {validatorConsensusAddress} | +| liveness | missed_blocks | {missedBlocksCounter} | +| liveness | height | {blockHeight} | + +#### Slash + +* same as `"slash"` event from `HandleValidatorSignature`, but without the `jailed` attribute. + +#### Jail + +| Type | Attribute Key | Attribute Value | +| ----- | ------------- | ------------------ | +| slash | jailed | {validatorAddress} | + +## Staking Tombstone + +### Abstract + +In the current implementation of the `slashing` module, when the consensus engine +informs the state machine of a validator's consensus fault, the validator is +partially slashed, and put into a "jail period", a period of time in which they +are not allowed to rejoin the validator set. However, because of the nature of +consensus faults and ABCI, there can be a delay between an infraction occurring, +and evidence of the infraction reaching the state machine (this is one of the +primary reasons for the existence of the unbonding period). + +> Note: The tombstone concept, only applies to faults that have a delay between +> the infraction occurring and evidence reaching the state machine. For example, +> evidence of a validator double signing may take a while to reach the state machine +> due to unpredictable evidence gossip layer delays and the ability of validators to +> selectively reveal double-signatures (e.g. to infrequently-online light clients). +> Liveness slashing, on the other hand, is detected immediately as soon as the +> infraction occurs, and therefore no slashing period is needed. A validator is +> immediately put into jail period, and they cannot commit another liveness fault +> until they unjail. In the future, there may be other types of byzantine faults +> that have delays (for example, submitting evidence of an invalid proposal as a transaction). +> When implemented, it will have to be decided whether these future types of +> byzantine faults will result in a tombstoning (and if not, the slash amounts +> will not be capped by a slashing period). + +In the current system design, once a validator is put in the jail for a consensus +fault, after the `JailPeriod` they are allowed to send a transaction to `unjail` +themselves, and thus rejoin the validator set. + +One of the "design desires" of the `slashing` module is that if multiple +infractions occur before evidence is executed (and a validator is put in jail), +they should only be punished for single worst infraction, but not cumulatively. +For example, if the sequence of events is: + +1. Validator A commits Infraction 1 (worth 30% slash) +2. Validator A commits Infraction 2 (worth 40% slash) +3. Validator A commits Infraction 3 (worth 35% slash) +4. Evidence for Infraction 1 reaches state machine (and validator is put in jail) +5. Evidence for Infraction 2 reaches state machine +6. Evidence for Infraction 3 reaches state machine + +Only Infraction 2 should have its slash take effect, as it is the highest. This +is done, so that in the case of the compromise of a validator's consensus key, +they will only be punished once, even if the hacker double-signs many blocks. +Because, the unjailing has to be done with the validator's operator key, they +have a chance to re-secure their consensus key, and then signal that they are +ready using their operator key. We call this period during which we track only +the max infraction, the "slashing period". + +Once, a validator rejoins by unjailing themselves, we begin a new slashing period; +if they commit a new infraction after unjailing, it gets slashed cumulatively on +top of the worst infraction from the previous slashing period. + +However, while infractions are grouped based off of the slashing periods, because +evidence can be submitted up to an `unbondingPeriod` after the infraction, we +still have to allow for evidence to be submitted for previous slashing periods. +For example, if the sequence of events is: + +1. Validator A commits Infraction 1 (worth 30% slash) +2. Validator A commits Infraction 2 (worth 40% slash) +3. Evidence for Infraction 1 reaches state machine (and Validator A is put in jail) +4. Validator A unjails + +We are now in a new slashing period, however we still have to keep the door open +for the previous infraction, as the evidence for Infraction 2 may still come in. +As the number of slashing periods increase, it creates more complexity as we have +to keep track of the highest infraction amount for every single slashing period. + +> Note: Currently, according to the `slashing` module spec, a new slashing period +> is created every time a validator is unbonded then rebonded. This should probably +> be changed to jailed/unjailed. See issue [#3205](https://github.com/cosmos/cosmos-sdk/issues/3205) +> for further details. For the remainder of this, I will assume that we only start +> a new slashing period when a validator gets unjailed. + +The maximum number of slashing periods is the `len(UnbondingPeriod) / len(JailPeriod)`. +The current defaults in Gaia for the `UnbondingPeriod` and `JailPeriod` are 3 weeks +and 2 days, respectively. This means there could potentially be up to 11 slashing +periods concurrently being tracked per validator. If we set the `JailPeriod >= UnbondingPeriod`, +we only have to track 1 slashing period (i.e not have to track slashing periods). + +Currently, in the jail period implementation, once a validator unjails, all of +their delegators who are delegated to them (haven't unbonded / redelegated away), +stay with them. Given that consensus safety faults are so egregious +(way more so than liveness faults), it is probably prudent to have delegators not +"auto-rebond" to the validator. + +#### Proposal: infinite jail + +We propose setting the "jail time" for a +validator who commits a consensus safety fault, to `infinite` (i.e. a tombstone state). +This essentially kicks the validator out of the validator set and does not allow +them to re-enter the validator set. All of their delegators (including the operator themselves) +have to either unbond or redelegate away. The validator operator can create a new +validator if they would like, with a new operator key and consensus key, but they +have to "re-earn" their delegations back. + +Implementing the tombstone system and getting rid of the slashing period tracking +will make the `slashing` module way simpler, especially because we can remove all +of the hooks defined in the `slashing` module consumed by the `staking` module +(the `slashing` module still consumes hooks defined in `staking`). + +#### Single slashing amount + +Another optimization that can be made is that if we assume that all ABCI faults +for CometBFT consensus are slashed at the same level, we don't have to keep +track of "max slash". Once an ABCI fault happens, we don't have to worry about +comparing potential future ones to find the max. + +Currently the only CometBFT ABCI fault is: + +* Unjustified precommits (double signs) + +It is currently planned to include the following fault in the near future: + +* Signing a precommit when you're in unbonding phase (needed to make light client bisection safe) + +Given that these faults are both attributable byzantine faults, we will likely +want to slash them equally, and thus we can enact the above change. + +> Note: This change may make sense for current CometBFT consensus, but maybe +> not for a different consensus algorithm or future versions of CometBFT that +> may want to punish at different levels (for example, partial slashing). + +## Parameters + +The slashing module contains the following parameters: + +| Key | Type | Example | +| ----------------------- | -------------- | ---------------------- | +| SignedBlocksWindow | string (int64) | "100" | +| MinSignedPerWindow | string (dec) | "0.500000000000000000" | +| DowntimeJailDuration | string (ns) | "600000000000" | +| SlashFractionDoubleSign | string (dec) | "0.050000000000000000" | +| SlashFractionDowntime | string (dec) | "0.010000000000000000" | + +## CLI + +A user can query and interact with the `slashing` module using the CLI. + +### Query + +The `query` commands allow users to query `slashing` state. + +```shell +simd query slashing --help +``` + +#### params + +The `params` command allows users to query genesis parameters for the slashing module. + +```shell +simd query slashing params [flags] +``` + +Example: + +```shell +simd query slashing params +``` + +Example Output: + +```yml +downtime_jail_duration: 600s +min_signed_per_window: "0.500000000000000000" +signed_blocks_window: "100" +slash_fraction_double_sign: "0.050000000000000000" +slash_fraction_downtime: "0.010000000000000000" +``` + +#### signing-info + +The `signing-info` command allows users to query signing-info of the validator using consensus public key. + +```shell +simd query slashing signing-infos [flags] +``` + +Example: + +```shell +simd query slashing signing-info '{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Auxs3865HpB/EfssYOzfqNhEJjzys6jD5B6tPgC8="}' + +``` + +Example Output: + +```yml +address: cosmosvalcons1nrqsld3aw6lh6t082frdqc84uwxn0t958c +index_offset: "2068" +jailed_until: "1970-01-01T00:00:00Z" +missed_blocks_counter: "0" +start_height: "0" +tombstoned: false +``` + +#### signing-infos + +The `signing-infos` command allows users to query signing infos of all validators. + +```shell +simd query slashing signing-infos [flags] +``` + +Example: + +```shell +simd query slashing signing-infos +``` + +Example Output: + +```yml +info: +- address: cosmosvalcons1nrqsld3aw6lh6t082frdqc84uwxn0t958c + index_offset: "2075" + jailed_until: "1970-01-01T00:00:00Z" + missed_blocks_counter: "0" + start_height: "0" + tombstoned: false +pagination: + next_key: null + total: "0" +``` + +### Transactions + +The `tx` commands allow users to interact with the `slashing` module. + +```bash +simd tx slashing --help +``` + +#### unjail + +The `unjail` command allows users to unjail a validator previously jailed for downtime. + +```bash +simd tx slashing unjail --from mykey [flags] +``` + +Example: + +```bash +simd tx slashing unjail --from mykey +``` + +### gRPC + +A user can query the `slashing` module using gRPC endpoints. + +#### Params + +The `Params` endpoint allows users to query the parameters of slashing module. + +```shell +cosmos.slashing.v1beta1.Query/Params +``` + +Example: + +```shell +grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/Params +``` + +Example Output: + +```json +{ + "params": { + "signedBlocksWindow": "100", + "minSignedPerWindow": "NTAwMDAwMDAwMDAwMDAwMDAw", + "downtimeJailDuration": "600s", + "slashFractionDoubleSign": "NTAwMDAwMDAwMDAwMDAwMDA=", + "slashFractionDowntime": "MTAwMDAwMDAwMDAwMDAwMDA=" + } +} +``` + +#### SigningInfo + +The SigningInfo queries the signing info of given cons address. + +```shell +cosmos.slashing.v1beta1.Query/SigningInfo +``` + +Example: + +```shell +grpcurl -plaintext -d '{"cons_address":"cosmosvalcons1nrqsld3aw6lh6t082frdqc84uwxn0t958c"}' localhost:9090 cosmos.slashing.v1beta1.Query/SigningInfo +``` + +Example Output: + +```json +{ + "valSigningInfo": { + "address": "cosmosvalcons1nrqsld3aw6lh6t082frdqc84uwxn0t958c", + "indexOffset": "3493", + "jailedUntil": "1970-01-01T00:00:00Z" + } +} +``` + +#### SigningInfos + +The SigningInfos queries signing info of all validators. + +```shell +cosmos.slashing.v1beta1.Query/SigningInfos +``` + +Example: + +```shell +grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/SigningInfos +``` + +Example Output: + +```json +{ + "info": [ + { + "address": "cosmosvalcons1nrqslkwd3pz096lh6t082frdqc84uwxn0t958c", + "indexOffset": "2467", + "jailedUntil": "1970-01-01T00:00:00Z" + } + ], + "pagination": { + "total": "1" + } +} +``` + +### REST + +A user can query the `slashing` module using REST endpoints. + +#### Params + +```shell +/cosmos/slashing/v1beta1/params +``` + +Example: + +```shell +curl "localhost:1317/cosmos/slashing/v1beta1/params" +``` + +Example Output: + +```json +{ + "params": { + "signed_blocks_window": "100", + "min_signed_per_window": "0.500000000000000000", + "downtime_jail_duration": "600s", + "slash_fraction_double_sign": "0.050000000000000000", + "slash_fraction_downtime": "0.010000000000000000" +} +``` + +#### signing_info + +```shell +/cosmos/slashing/v1beta1/signing_infos/%s +``` + +Example: + +```shell +curl "localhost:1317/cosmos/slashing/v1beta1/signing_infos/cosmosvalcons1nrqslkwd3pz096lh6t082frdqc84uwxn0t958c" +``` + +Example Output: + +```json +{ + "val_signing_info": { + "address": "cosmosvalcons1nrqslkwd3pz096lh6t082frdqc84uwxn0t958c", + "start_height": "0", + "index_offset": "4184", + "jailed_until": "1970-01-01T00:00:00Z", + "tombstoned": false, + "missed_blocks_counter": "0" + } +} +``` + +#### signing_infos + +```shell +/cosmos/slashing/v1beta1/signing_infos +``` + +Example: + +```shell +curl "localhost:1317/cosmos/slashing/v1beta1/signing_infos +``` + +Example Output: + +```json +{ + "info": [ + { + "address": "cosmosvalcons1nrqslkwd3pz096lh6t082frdqc84uwxn0t958c", + "start_height": "0", + "index_offset": "4169", + "jailed_until": "1970-01-01T00:00:00Z", + "tombstoned": false, + "missed_blocks_counter": "0" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/staking/README.md b/versioned_docs/version-0.47/integrate/modules/staking/README.md new file mode 100644 index 000000000..5dd94dc69 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/staking/README.md @@ -0,0 +1,3058 @@ +--- +sidebar_position: 1 +--- + +# `x/staking` + +## Abstract + +This paper specifies the Staking module of the Cosmos SDK that was first +described in the [Cosmos Whitepaper](https://cosmos.network/about/whitepaper) +in June 2016. + +The module enables Cosmos SDK-based blockchain to support an advanced +Proof-of-Stake (PoS) system. In this system, holders of the native staking token of +the chain can become validators and can delegate tokens to validators, +ultimately determining the effective validator set for the system. + +This module is used in the Cosmos Hub, the first Hub in the Cosmos +network. + +## Contents + +* [State](#state) + * [Pool](#pool) + * [LastTotalPower](#lasttotalpower) + * [ValidatorUpdates](#validatorupdates) + * [UnbondingID](#unbondingid) + * [Params](#params) + * [Validator](#validator) + * [Delegation](#delegation) + * [UnbondingDelegation](#unbondingdelegation) + * [Redelegation](#redelegation) + * [Queues](#queues) + * [HistoricalInfo](#historicalinfo) +* [State Transitions](#state-transitions) + * [Validators](#validators) + * [Delegations](#delegations) + * [Slashing](#slashing) + * [How Shares are calculated](#how-shares-are-calculated) +* [Messages](#messages) + * [MsgCreateValidator](#msgcreatevalidator) + * [MsgEditValidator](#msgeditvalidator) + * [MsgDelegate](#msgdelegate) + * [MsgUndelegate](#msgundelegate) + * [MsgCancelUnbondingDelegation](#msgcancelunbondingdelegation) + * [MsgBeginRedelegate](#msgbeginredelegate) + * [MsgUpdateParams](#msgupdateparams) +* [Begin-Block](#begin-block) + * [Historical Info Tracking](#historical-info-tracking) +* [End-Block](#end-block) + * [Validator Set Changes](#validator-set-changes) + * [Queues](#queues-1) +* [Hooks](#hooks) +* [Events](#events) + * [EndBlocker](#endblocker) + * [Msg's](#msgs) +* [Parameters](#parameters) +* [Client](#client) + * [CLI](#cli) + * [gRPC](#grpc) + * [REST](#rest) + +## State + +### Pool + +Pool is used for tracking bonded and not-bonded token supply of the bond denomination. + +### LastTotalPower + +LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. +Store entries prefixed with "Last" must remain unchanged until EndBlock. + +* LastTotalPower: `0x12 -> ProtocolBuffer(math.Int)` + +### ValidatorUpdates + +ValidatorUpdates contains the validator updates returned to ABCI at the end of every block. +The values are overwritten in every block. + +* ValidatorUpdates `0x61 -> []abci.ValidatorUpdate` + +### UnbondingID + +UnbondingID stores the ID of the latest unbonding operation. It enables to create unique IDs for unbonding operation, i.e., UnbondingID is incremented every time a new unbonding operation (validator unbonding, unbonding delegation, redelegation) is initiated. + +* UnbondingID: `0x37 -> uint64` + +### Params + +The staking module stores its params in state with the prefix of `0x51`, +it can be updated with governance or the address with authority. + +* Params: `0x51 | ProtocolBuffer(Params)` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L310-L333 +``` + +### Validator + +Validators can have one of three statuses + +* `Unbonded`: The validator is not in the active set. They cannot sign blocks and do not earn + rewards. They can receive delegations. +* `Bonded`: Once the validator receives sufficient bonded tokens they automatically join the + active set during [`EndBlock`](#validator-set-changes) and their status is updated to `Bonded`. + They are signing blocks and receiving rewards. They can receive further delegations. + They can be slashed for misbehavior. Delegators to this validator who unbond their delegation + must wait the duration of the UnbondingTime, a chain-specific param, during which time + they are still slashable for offences of the source validator if those offences were committed + during the period of time that the tokens were bonded. +* `Unbonding`: When a validator leaves the active set, either by choice or due to slashing, jailing or + tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime + before their tokens are moved to their accounts from the `BondedPool`. + +:::warning +Tombstoning is permanent, once tombstoned a validators consensus key can not be reused within the chain where the tombstoning happened. +::: + +Validators objects should be primarily stored and accessed by the +`OperatorAddr`, an SDK validator address for the operator of the validator. Two +additional indices are maintained per validator object in order to fulfill +required lookups for slashing and validator-set updates. A third special index +(`LastValidatorPower`) is also maintained which however remains constant +throughout each block, unlike the first two indices which mirror the validator +records within a block. + +* Validators: `0x21 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(validator)` +* ValidatorsByConsAddr: `0x22 | ConsAddrLen (1 byte) | ConsAddr -> OperatorAddr` +* ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddrLen (1 byte) | OperatorAddr -> OperatorAddr` +* LastValidatorsPower: `0x11 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(ConsensusPower)` +* ValidatorsByUnbondingID: `0x38 | UnbondingID -> 0x21 | OperatorAddrLen (1 byte) | OperatorAddr` + +`Validators` is the primary index - it ensures that each operator can have only one +associated validator, where the public key of that validator can change in the +future. Delegators can refer to the immutable operator of the validator, without +concern for the changing public key. + +`ValidatorsByUnbondingID` is an additional index that enables lookups for + validators by the unbonding IDs corresponding to their current unbonding. + +`ValidatorByConsAddr` is an additional index that enables lookups for slashing. +When CometBFT reports evidence, it provides the validator address, so this +map is needed to find the operator. Note that the `ConsAddr` corresponds to the +address which can be derived from the validator's `ConsPubKey`. + +`ValidatorsByPower` is an additional index that provides a sorted list of +potential validators to quickly determine the current active set. Here +ConsensusPower is validator.Tokens/10^6 by default. Note that all validators +where `Jailed` is true are not stored within this index. + +`LastValidatorsPower` is a special index that provides a historical list of the +last-block's bonded validators. This index remains constant during a block but +is updated during the validator set update process which takes place in [`EndBlock`](#end-block). + +Each validator's state is stored in a `Validator` struct: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L82-L138 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L26-L80 +``` + +### Delegation + +Delegations are identified by combining `DelegatorAddr` (the address of the delegator) +with the `ValidatorAddr` Delegators are indexed in the store as follows: + +* Delegation: `0x31 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(delegation)` + +Stake holders may delegate coins to validators; under this circumstance their +funds are held in a `Delegation` data structure. It is owned by one +delegator, and is associated with the shares for one validator. The sender of +the transaction is the owner of the bond. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L198-L216 +``` + +#### Delegator Shares + +When one Delegates tokens to a Validator they are issued a number of delegator shares based on a +dynamic exchange rate, calculated as follows from the total number of tokens delegated to the +validator and the number of shares issued so far: + +`Shares per Token = validator.TotalShares() / validator.Tokens()` + +Only the number of shares received is stored on the DelegationEntry. When a delegator then +Undelegates, the token amount they receive is calculated from the number of shares they currently +hold and the inverse exchange rate: + +`Tokens per Share = validator.Tokens() / validatorShares()` + +These `Shares` are simply an accounting mechanism. They are not a fungible asset. The reason for +this mechanism is to simplify the accounting around slashing. Rather than iteratively slashing the +tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, +effectively reducing the value of each issued delegator share. + +### UnbondingDelegation + +Shares in a `Delegation` can be unbonded, but they must for some time exist as +an `UnbondingDelegation`, where shares can be reduced if Byzantine behavior is +detected. + +`UnbondingDelegation` are indexed in the store as: + +* UnbondingDelegation: `0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` +* UnbondingDelegationsFromValidator: `0x33 | ValidatorAddrLen (1 byte) | ValidatorAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` +* UnbondingDelegationByUnbondingId: `0x38 | UnbondingId -> 0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr` + `UnbondingDelegation` is used in queries, to lookup all unbonding delegations for + a given delegator. + +`UnbondingDelegationsFromValidator` is used in slashing, to lookup all + unbonding delegations associated with a given validator that need to be + slashed. + + `UnbondingDelegationByUnbondingId` is an additional index that enables + lookups for unbonding delegations by the unbonding IDs of the containing + unbonding delegation entries. + + +A UnbondingDelegation object is created every time an unbonding is initiated. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L218-L261 +``` + +### Redelegation + +The bonded tokens worth of a `Delegation` may be instantly redelegated from a +source validator to a different validator (destination validator). However when +this occurs they must be tracked in a `Redelegation` object, whereby their +shares can be slashed if their tokens have contributed to a Byzantine fault +committed by the source validator. + +`Redelegation` are indexed in the store as: + +* Redelegations: `0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` +* RedelegationsBySrc: `0x35 | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` +* RedelegationsByDst: `0x36 | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` +* RedelegationByUnbondingId: `0x38 | UnbondingId -> 0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr` + + `Redelegations` is used for queries, to lookup all redelegations for a given + delegator. + + `RedelegationsBySrc` is used for slashing based on the `ValidatorSrcAddr`. + + `RedelegationsByDst` is used for slashing based on the `ValidatorDstAddr` + +The first map here is used for queries, to lookup all redelegations for a given +delegator. The second map is used for slashing based on the `ValidatorSrcAddr`, +while the third map is for slashing based on the `ValidatorDstAddr`. + +`RedelegationByUnbondingId` is an additional index that enables + lookups for redelegations by the unbonding IDs of the containing + redelegation entries. + +A redelegation object is created every time a redelegation occurs. To prevent +"redelegation hopping" redelegations may not occur under the situation that: + +* the (re)delegator already has another immature redelegation in progress + with a destination to a validator (let's call it `Validator X`) +* and, the (re)delegator is attempting to create a _new_ redelegation + where the source validator for this new redelegation is `Validator X`. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L263-L308 +``` + +### Queues + +All queues objects are sorted by timestamp. The time used within any queue is +first rounded to the nearest nanosecond then sorted. The sortable time format +used is a slight modification of the RFC3339Nano and uses the format string +`"2006-01-02T15:04:05.000000000"`. Notably this format: + +* right pads all zeros +* drops the time zone info (uses UTC) + +In all cases, the stored timestamp represents the maturation time of the queue +element. + +#### UnbondingDelegationQueue + +For the purpose of tracking progress of unbonding delegations the unbonding +delegations queue is kept. + +* UnbondingDelegation: `0x41 | format(time) -> []DVPair` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L162-L172 +``` + +#### RedelegationQueue + +For the purpose of tracking progress of redelegations the redelegation queue is +kept. + +* RedelegationQueue: `0x42 | format(time) -> []DVVTriplet` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L179-L191 +``` + +#### ValidatorQueue + +For the purpose of tracking progress of unbonding validators the validator +queue is kept. + +* ValidatorQueueTime: `0x43 | format(time) -> []sdk.ValAddress` + +The stored object as each key is an array of validator operator addresses from +which the validator object can be accessed. Typically it is expected that only +a single validator record will be associated with a given timestamp however it is possible +that multiple validators exist in the queue at the same location. + +### HistoricalInfo + +HistoricalInfo objects are stored and pruned at each block such that the staking keeper persists +the `n` most recent historical info defined by staking module parameter: `HistoricalEntries`. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/staking.proto#L17-L24 +``` + +At each BeginBlock, the staking keeper will persist the current Header and the Validators that committed +the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that +they are in a deterministic order. +The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of +historical entries. + +## State Transitions + +### Validators + +State transitions in validators are performed on every [`EndBlock`](#validator-set-changes) +in order to check for changes in the active `ValidatorSet`. + +A validator can be `Unbonded`, `Unbonding` or `Bonded`. `Unbonded` +and `Unbonding` are collectively called `Not Bonded`. A validator can move +directly between all the states, except for from `Bonded` to `Unbonded`. + +#### Not bonded to Bonded + +The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses +that of the `LastValidator`. + +* set `validator.Status` to `Bonded` +* send the `validator.Tokens` from the `NotBondedTokens` to the `BondedPool` `ModuleAccount` +* delete the existing record from `ValidatorByPowerIndex` +* add a new updated record to the `ValidatorByPowerIndex` +* update the `Validator` object for this validator +* if it exists, delete any `ValidatorQueue` record for this validator + +#### Bonded to Unbonding + +When a validator begins the unbonding process the following operations occur: + +* send the `validator.Tokens` from the `BondedPool` to the `NotBondedTokens` `ModuleAccount` +* set `validator.Status` to `Unbonding` +* delete the existing record from `ValidatorByPowerIndex` +* add a new updated record to the `ValidatorByPowerIndex` +* update the `Validator` object for this validator +* insert a new record into the `ValidatorQueue` for this validator + +#### Unbonding to Unbonded + +A validator moves from unbonding to unbonded when the `ValidatorQueue` object +moves from bonded to unbonded + +* update the `Validator` object for this validator +* set `validator.Status` to `Unbonded` + +#### Jail/Unjail + +when a validator is jailed it is effectively removed from the CometBFT set. +this process may be also be reversed. the following operations occur: + +* set `Validator.Jailed` and update object +* if jailed delete record from `ValidatorByPowerIndex` +* if unjailed add record to `ValidatorByPowerIndex` + +Jailed validators are not present in any of the following stores: + +* the power store (from consensus power to address) + +### Delegations + +#### Delegate + +When a delegation occurs both the validator and the delegation objects are affected + +* determine the delegators shares based on tokens delegated and the validator's exchange rate +* remove tokens from the sending account +* add shares the delegation object or add them to a created validator object +* add new delegator shares and update the `Validator` object +* transfer the `delegation.Amount` from the delegator's account to the `BondedPool` or the `NotBondedPool` `ModuleAccount` depending if the `validator.Status` is `Bonded` or not +* delete the existing record from `ValidatorByPowerIndex` +* add an new updated record to the `ValidatorByPowerIndex` + +#### Begin Unbonding + +As a part of the Undelegate and Complete Unbonding state transitions Unbond +Delegation may be called. + +* subtract the unbonded shares from delegator +* add the unbonded tokens to an `UnbondingDelegationEntry` +* update the delegation or remove the delegation if there are no more shares +* if the delegation is the operator of the validator and no more shares exist then trigger a jail validator +* update the validator with removed the delegator shares and associated coins +* if the validator state is `Bonded`, transfer the `Coins` worth of the unbonded + shares from the `BondedPool` to the `NotBondedPool` `ModuleAccount` +* remove the validator if it is unbonded and there are no more delegation shares. +* remove the validator if it is unbonded and there are no more delegation shares +* get a unique `unbondingId` and map it to the `UnbondingDelegationEntry` in `UnbondingDelegationByUnbondingId` +* call the `AfterUnbondingInitiated(unbondingId)` hook +* add the unbonding delegation to `UnbondingDelegationQueue` with the completion time set to `UnbondingTime` + +#### Cancel an `UnbondingDelegation` Entry + +When a `cancel unbond delegation` occurs both the `validator`, the `delegation` and an `UnbondingDelegationQueue` state will be updated. + +* if cancel unbonding delegation amount equals to the `UnbondingDelegation` entry `balance`, then the `UnbondingDelegation` entry deleted from `UnbondingDelegationQueue`. +* if the `cancel unbonding delegation amount is less than the `UnbondingDelegation` entry balance, then the `UnbondingDelegation` entry will be updated with new balance in the `UnbondingDelegationQueue`. +* cancel `amount` is [Delegated](#delegations) back to the original `validator`. + +#### Complete Unbonding + +For undelegations which do not complete immediately, the following operations +occur when the unbonding delegation queue element matures: + +* remove the entry from the `UnbondingDelegation` object +* transfer the tokens from the `NotBondedPool` `ModuleAccount` to the delegator `Account` + +#### Begin Redelegation + +Redelegations affect the delegation, source and destination validators. + +* perform an `unbond` delegation from the source validator to retrieve the tokens worth of the unbonded shares +* using the unbonded tokens, `Delegate` them to the destination validator +* if the `sourceValidator.Status` is `Bonded`, and the `destinationValidator` is not, + transfer the newly delegated tokens from the `BondedPool` to the `NotBondedPool` `ModuleAccount` +* otherwise, if the `sourceValidator.Status` is not `Bonded`, and the `destinationValidator` + is `Bonded`, transfer the newly delegated tokens from the `NotBondedPool` to the `BondedPool` `ModuleAccount` +* record the token amount in an new entry in the relevant `Redelegation` + +From when a redelegation begins until it completes, the delegator is in a state of "pseudo-unbonding", and can still be +slashed for infractions that occurred before the redelegation began. + +#### Complete Redelegation + +When a redelegations complete the following occurs: + +* remove the entry from the `Redelegation` object + +### Slashing + +#### Slash Validator + +When a Validator is slashed, the following occurs: + +* The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) \* `TokensFromConsensusPower`, + the total number of tokens bonded to the validator at the time of the infraction. +* Every unbonding delegation and pseudo-unbonding redelegation such that the infraction occured before the unbonding or + redelegation began from the validator are slashed by the `slashFactor` percentage of the initialBalance. +* Each amount slashed from redelegations and unbonding delegations is subtracted from the + total slash amount. +* The `remaingSlashAmount` is then slashed from the validator's tokens in the `BondedPool` or + `NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. + +In the case of a slash due to any infraction that requires evidence to submitted (for example double-sign), the slash +occurs at the block where the evidence is included, not at the block where the infraction occured. +Put otherwise, validators are not slashed retroactively, only when they are caught. + +#### Slash Unbonding Delegation + +When a validator is slashed, so are those unbonding delegations from the validator that began unbonding +after the time of the infraction. Every entry in every unbonding delegation from the validator +is slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the +delegation and is capped to prevent a resulting negative balance. Completed (or mature) unbondings are not slashed. + +#### Slash Redelegation + +When a validator is slashed, so are all redelegations from the validator that began after the +infraction. Redelegations are slashed by `slashFactor`. +Redelegations that began before the infraction are not slashed. +The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to +prevent a resulting negative balance. +Mature redelegations (that have completed pseudo-unbonding) are not slashed. + +### How Shares are calculated + +At any given point in time, each validator has a number of tokens, `T`, and has a number of shares issued, `S`. +Each delegator, `i`, holds a number of shares, `S_i`. +The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes. + +The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. +So delegator `i` is entitled to `T * S_i / S` of the validator's tokens. + +When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. +So when delegator `j` delegates `T_j` tokens, they receive `S_j = S * T_j / T` shares. +The total number of tokens is now `T + T_j`, and the total number of shares is `S + S_j`. +`j`s proportion of the shares is the same as their proportion of the total tokens contributed: `(S + S_j) / S = (T + T_j) / T`. + +A special case is the initial delegation, when `T = 0` and `S = 0`, so `T_j / T` is undefined. +For the initial delegation, delegator `j` who delegates `T_j` tokens receive `S_j = T_j` shares. +So a validator that hasn't received any rewards and has not been slashed will have `T = S`. + +## Messages + +In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the [state](#state) section. + +### MsgCreateValidator + +A validator is created using the `MsgCreateValidator` message. +The validator must be created with an initial delegation from the operator. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L20-L21 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L50-L73 +``` + +This message is expected to fail if: + +* another validator with this operator address is already registered +* another validator with this pubkey is already registered +* the initial self-delegation tokens are of a denom not specified as the bonding denom +* the commission parameters are faulty, namely: + * `MaxRate` is either > 1 or < 0 + * the initial `Rate` is either negative or > `MaxRate` + * the initial `MaxChangeRate` is either negative or > `MaxRate` +* the description fields are too large + +This message creates and stores the `Validator` object at appropriate indexes. +Additionally a self-delegation is made with the initial tokens delegation +tokens `Delegation`. The validator always starts as unbonded but may be bonded +in the first end-block. + +### MsgEditValidator + +The `Description`, `CommissionRate` of a validator can be updated using the +`MsgEditValidator` message. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L23-L24 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L78-L97 +``` + +This message is expected to fail if: + +* the initial `CommissionRate` is either negative or > `MaxRate` +* the `CommissionRate` has already been updated within the previous 24 hours +* the `CommissionRate` is > `MaxChangeRate` +* the description fields are too large + +This message stores the updated `Validator` object. + +### MsgDelegate + +Within this message the delegator provides coins, and in return receives +some amount of their validator's (newly created) delegator-shares that are +assigned to `Delegation.Shares`. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L26-L28 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L102-L114 +``` + +This message is expected to fail if: + +* the validator does not exist +* the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` +* the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares +* the amount delegated is less than the minimum allowed delegation + +If an existing `Delegation` object for provided addresses does not already +exist then it is created as part of this message otherwise the existing +`Delegation` is updated to include the newly received shares. + +The delegator receives newly minted shares at the current exchange rate. +The exchange rate is the number of existing shares in the validator divided by +the number of currently delegated tokens. + +The validator is updated in the `ValidatorByPower` index, and the delegation is +tracked in validator object in the `Validators` index. + +It is possible to delegate to a jailed validator, the only difference being it +will not be added to the power index until it is unjailed. + +![Delegation sequence](https://raw.githubusercontent.com/cosmos/cosmos-sdk/release/v0.46.x/docs/uml/svg/delegation_sequence.svg) + +### MsgUndelegate + +The `MsgUndelegate` message allows delegators to undelegate their tokens from +validator. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L34-L36 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L140-L152 +``` + +This message returns a response containing the completion time of the undelegation: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L154-L158 +``` + +This message is expected to fail if: + +* the delegation doesn't exist +* the validator doesn't exist +* the delegation has less shares than the ones worth of `Amount` +* existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries` +* the `Amount` has a denomination different than one defined by `params.BondDenom` + +When this message is processed the following actions occur: + +* validator's `DelegatorShares` and the delegation's `Shares` are both reduced by the message `SharesAmount` +* calculate the token worth of the shares remove that amount tokens held within the validator +* with those removed tokens, if the validator is: + * `Bonded` - add them to an entry in `UnbondingDelegation` (create `UnbondingDelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares. + * `Unbonding` - add them to an entry in `UnbondingDelegation` (create `UnbondingDelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`). + * `Unbonded` - then send the coins the message `DelegatorAddr` +* if there are no more `Shares` in the delegation, then the delegation object is removed from the store + * under this situation if the delegation is the validator's self-delegation then also jail the validator. + +![Unbond sequence](https://raw.githubusercontent.com/cosmos/cosmos-sdk/release/v0.46.x/docs/uml/svg/unbond_sequence.svg) + +### MsgCancelUnbondingDelegation + +The `MsgCancelUnbondingDelegation` message allows delegators to cancel the `unbondingDelegation` entry and delegate back to a previous validator. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L38-L42 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L160-L175 +``` + +This message is expected to fail if: + +* the `unbondingDelegation` entry is already processed. +* the `cancel unbonding delegation` amount is greater than the `unbondingDelegation` entry balance. +* the `cancel unbonding delegation` height doesn't exist in the `unbondingDelegationQueue` of the delegator. + +When this message is processed the following actions occur: + +* if the `unbondingDelegation` Entry balance is zero + * in this condition `unbondingDelegation` entry will be removed from `unbondingDelegationQueue`. + * otherwise `unbondingDelegationQueue` will be updated with new `unbondingDelegation` entry balance and initial balance +* the validator's `DelegatorShares` and the delegation's `Shares` are both increased by the message `Amount`. + +### MsgBeginRedelegate + +The redelegation command allows delegators to instantly switch validators. Once +the unbonding period has passed, the redelegation is automatically completed in +the EndBlocker. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L30-L32 +``` + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L119-L132 +``` + +This message returns a response containing the completion time of the redelegation: + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L133-L138 +``` + +This message is expected to fail if: + +* the delegation doesn't exist +* the source or destination validators don't exist +* the delegation has less shares than the ones worth of `Amount` +* the source validator has a receiving redelegation which is not matured (aka. the redelegation may be transitive) +* existing `Redelegation` has maximum entries as defined by `params.MaxEntries` +* the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` + +When this message is processed the following actions occur: + +* the source validator's `DelegatorShares` and the delegations `Shares` are both reduced by the message `SharesAmount` +* calculate the token worth of the shares remove that amount tokens held within the source validator. +* if the source validator is: + * `Bonded` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares (this may be effectively reversed in the next step however). + * `Unbonding` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`). + * `Unbonded` - no action required in this step +* Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. +* if there are no more `Shares` in the source delegation, then the source delegation object is removed from the store + * under this situation if the delegation is the validator's self-delegation then also jail the validator. + +![Begin redelegation sequence](https://raw.githubusercontent.com/cosmos/cosmos-sdk/release/v0.46.x/docs/uml/svg/begin_redelegation_sequence.svg) + + +### MsgUpdateParams + +The `MsgUpdateParams` update the staking module parameters. +The params are updated through a governance proposal where the signer is the gov module account address. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/tx.proto#L182-L195 +``` + +The message handling can fail if: + +* signer is not the authority defined in the staking keeper (usually the gov module account). + +## Begin-Block + +Each abci begin block call, the historical info will get stored and pruned +according to the `HistoricalEntries` parameter. + +### Historical Info Tracking + +If the `HistoricalEntries` parameter is 0, then the `BeginBlock` performs a no-op. + +Otherwise, the latest historical info is stored under the key `historicalInfoKey|height`, while any entries older than `height - HistoricalEntries` is deleted. +In most cases, this results in a single entry being pruned per block. +However, if the parameter `HistoricalEntries` has changed to a lower value there will be multiple entries in the store that must be pruned. + +## End-Block + +Each abci end block call, the operations to update queues and validator set +changes are specified to execute. + +### Validator Set Changes + +The staking validator set is updated during this process by state transitions +that run at the end of every block. As a part of this process any updated +validators are also returned back to CometBFT for inclusion in the CometBFT +validator set which is responsible for validating CometBFT messages at the +consensus layer. Operations are as following: + +* the new validator set is taken as the top `params.MaxValidators` number of + validators retrieved from the `ValidatorsByPower` index +* the previous validator set is compared with the new validator set: + * missing validators begin unbonding and their `Tokens` are transferred from the + `BondedPool` to the `NotBondedPool` `ModuleAccount` + * new validators are instantly bonded and their `Tokens` are transferred from the + `NotBondedPool` to the `BondedPool` `ModuleAccount` + +In all cases, any validators leaving or entering the bonded validator set or +changing balances and staying within the bonded validator set incur an update +message reporting their new consensus power which is passed back to CometBFT. + +The `LastTotalPower` and `LastValidatorsPower` hold the state of the total power +and validator power from the end of the last block, and are used to check for +changes that have occurred in `ValidatorsByPower` and the total new power, which +is calculated during `EndBlock`. + +### Queues + +Within staking, certain state-transitions are not instantaneous but take place +over a duration of time (typically the unbonding period). When these +transitions are mature certain operations must take place in order to complete +the state operation. This is achieved through the use of queues which are +checked/processed at the end of each block. + +#### Unbonding Validators + +When a validator is kicked out of the bonded validator set (either through +being jailed, or not having sufficient bonded tokens) it begins the unbonding +process along with all its delegations begin unbonding (while still being +delegated to this validator). At this point the validator is said to be an +"unbonding validator", whereby it will mature to become an "unbonded validator" +after the unbonding period has passed. + +Each block the validator queue is to be checked for mature unbonding validators +(namely with a completion time <= current time and completion height <= current +block height). At this point any mature validators which do not have any +delegations remaining are deleted from state. For all other mature unbonding +validators that still have remaining delegations, the `validator.Status` is +switched from `types.Unbonding` to +`types.Unbonded`. + +Unbonding operations can be put on hold by external modules via the `PutUnbondingOnHold(unbondingId)` method. + As a result, an unbonding operation (e.g., an unbonding delegation) that is on hold, cannot complete + even if it reaches maturity. For an unbonding operation with `unbondingId` to eventually complete + (after it reaches maturity), every call to `PutUnbondingOnHold(unbondingId)` must be matched + by a call to `UnbondingCanComplete(unbondingId)`. + +#### Unbonding Delegations + +Complete the unbonding of all mature `UnbondingDelegations.Entries` within the +`UnbondingDelegations` queue with the following procedure: + +* transfer the balance coins to the delegator's wallet address +* remove the mature entry from `UnbondingDelegation.Entries` +* remove the `UnbondingDelegation` object from the store if there are no + remaining entries. + +#### Redelegations + +Complete the unbonding of all mature `Redelegation.Entries` within the +`Redelegations` queue with the following procedure: + +* remove the mature entry from `Redelegation.Entries` +* remove the `Redelegation` object from the store if there are no + remaining entries. + +## Hooks + +Other modules may register operations to execute when a certain event has +occurred within staking. These events can be registered to execute either +right `Before` or `After` the staking event (as per the hook name). The +following hooks can registered with staking: + +* `AfterValidatorCreated(Context, ValAddress) error` + * called when a validator is created +* `BeforeValidatorModified(Context, ValAddress) error` + * called when a validator's state is changed +* `AfterValidatorRemoved(Context, ConsAddress, ValAddress) error` + * called when a validator is deleted +* `AfterValidatorBonded(Context, ConsAddress, ValAddress) error` + * called when a validator is bonded +* `AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress) error` + * called when a validator begins unbonding +* `BeforeDelegationCreated(Context, AccAddress, ValAddress) error` + * called when a delegation is created +* `BeforeDelegationSharesModified(Context, AccAddress, ValAddress) error` + * called when a delegation's shares are modified +* `AfterDelegationModified(Context, AccAddress, ValAddress) error` + * called when a delegation is created or modified +* `BeforeDelegationRemoved(Context, AccAddress, ValAddress) error` + * called when a delegation is removed +* `AfterUnbondingInitiated(Context, UnbondingID)` + * called when an unbonding operation (validator unbonding, unbonding delegation, redelegation) was initiated + + +## Events + +The staking module emits the following events: + +### EndBlocker + +| Type | Attribute Key | Attribute Value | +| --------------------- | --------------------- | ------------------------- | +| complete_unbonding | amount | {totalUnbondingAmount} | +| complete_unbonding | validator | {validatorAddress} | +| complete_unbonding | delegator | {delegatorAddress} | +| complete_redelegation | amount | {totalRedelegationAmount} | +| complete_redelegation | source_validator | {srcValidatorAddress} | +| complete_redelegation | destination_validator | {dstValidatorAddress} | +| complete_redelegation | delegator | {delegatorAddress} | + +## Msg's + +### MsgCreateValidator + +| Type | Attribute Key | Attribute Value | +| ---------------- | ------------- | ------------------ | +| create_validator | validator | {validatorAddress} | +| create_validator | amount | {delegationAmount} | +| message | module | staking | +| message | action | create_validator | +| message | sender | {senderAddress} | + +### MsgEditValidator + +| Type | Attribute Key | Attribute Value | +| -------------- | ------------------- | ------------------- | +| edit_validator | commission_rate | {commissionRate} | +| edit_validator | min_self_delegation | {minSelfDelegation} | +| message | module | staking | +| message | action | edit_validator | +| message | sender | {senderAddress} | + +### MsgDelegate + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| delegate | validator | {validatorAddress} | +| delegate | amount | {delegationAmount} | +| message | module | staking | +| message | action | delegate | +| message | sender | {senderAddress} | + +### MsgUndelegate + +| Type | Attribute Key | Attribute Value | +| ------- | ------------------- | ------------------ | +| unbond | validator | {validatorAddress} | +| unbond | amount | {unbondAmount} | +| unbond | completion_time [0] | {completionTime} | +| message | module | staking | +| message | action | begin_unbonding | +| message | sender | {senderAddress} | + +* [0] Time is formatted in the RFC3339 standard + +### MsgCancelUnbondingDelegation + +| Type | Attribute Key | Attribute Value | +| ----------------------------- | ------------------ | ------------------------------------| +| cancel_unbonding_delegation | validator | {validatorAddress} | +| cancel_unbonding_delegation | delegator | {delegatorAddress} | +| cancel_unbonding_delegation | amount | {cancelUnbondingDelegationAmount} | +| cancel_unbonding_delegation | creation_height | {unbondingCreationHeight} | +| message | module | staking | +| message | action | cancel_unbond | +| message | sender | {senderAddress} | + +### MsgBeginRedelegate + +| Type | Attribute Key | Attribute Value | +| ---------- | --------------------- | --------------------- | +| redelegate | source_validator | {srcValidatorAddress} | +| redelegate | destination_validator | {dstValidatorAddress} | +| redelegate | amount | {unbondAmount} | +| redelegate | completion_time [0] | {completionTime} | +| message | module | staking | +| message | action | begin_redelegate | +| message | sender | {senderAddress} | + +* [0] Time is formatted in the RFC3339 standard + +## Parameters + +The staking module contains the following parameters: + +| Key | Type | Example | +|-------------------|------------------|------------------------| +| UnbondingTime | string (time ns) | "259200000000000" | +| MaxValidators | uint16 | 100 | +| KeyMaxEntries | uint16 | 7 | +| HistoricalEntries | uint16 | 3 | +| BondDenom | string | "stake" | +| MinCommissionRate | string | "0.000000000000000000" | + +## Client + +### CLI + +A user can query and interact with the `staking` module using the CLI. + +#### Query + +The `query` commands allows users to query `staking` state. + +```bash +simd query staking --help +``` + +##### delegation + +The `delegation` command allows users to query delegations for an individual delegator on an individual validator. + +Usage: + +```bash +simd query staking delegation [delegator-addr] [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking delegation cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +balance: + amount: "10000000000" + denom: stake +delegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + shares: "10000000000.000000000000000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +##### delegations + +The `delegations` command allows users to query delegations for an individual delegator on all validators. + +Usage: + +```bash +simd query staking delegations [delegator-addr] [flags] +``` + +Example: + +```bash +simd query staking delegations cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +``` + +Example Output: + +```bash +delegation_responses: +- balance: + amount: "10000000000" + denom: stake + delegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + shares: "10000000000.000000000000000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +- balance: + amount: "10000000000" + denom: stake + delegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + shares: "10000000000.000000000000000000" + validator_address: cosmosvaloper1x20lytyf6zkcrv5edpkfkn8sz578qg5sqfyqnp +pagination: + next_key: null + total: "0" +``` + +##### delegations-to + +The `delegations-to` command allows users to query delegations on an individual validator. + +Usage: + +```bash +simd query staking delegations-to [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking delegations-to cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +- balance: + amount: "504000000" + denom: stake + delegation: + delegator_address: cosmos1q2qwwynhv8kh3lu5fkeex4awau9x8fwt45f5cp + shares: "504000000.000000000000000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +- balance: + amount: "78125000000" + denom: uixo + delegation: + delegator_address: cosmos1qvppl3479hw4clahe0kwdlfvf8uvjtcd99m2ca + shares: "78125000000.000000000000000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +pagination: + next_key: null + total: "0" +``` + +##### historical-info + +The `historical-info` command allows users to query historical information at given height. + +Usage: + +```bash +simd query staking historical-info [height] [flags] +``` + +Example: + +```bash +simd query staking historical-info 10 +``` + +Example Output: + +```bash +header: + app_hash: Lbx8cXpI868wz8sgp4qPYVrlaKjevR5WP/IjUxwp3oo= + chain_id: testnet + consensus_hash: BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8= + data_hash: 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= + evidence_hash: 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= + height: "10" + last_block_id: + hash: RFbkpu6pWfSThXxKKl6EZVDnBSm16+U0l0xVjTX08Fk= + part_set_header: + hash: vpIvXD4rxD5GM4MXGz0Sad9I7//iVYLzZsEU4BVgWIU= + total: 1 + last_commit_hash: Ne4uXyx4QtNp4Zx89kf9UK7oG9QVbdB6e7ZwZkhy8K0= + last_results_hash: 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= + next_validators_hash: nGBgKeWBjoxeKFti00CxHsnULORgKY4LiuQwBuUrhCs= + proposer_address: mMEP2c2IRPLr99LedSRtBg9eONM= + time: "2021-10-01T06:00:49.785790894Z" + validators_hash: nGBgKeWBjoxeKFti00CxHsnULORgKY4LiuQwBuUrhCs= + version: + app: "0" + block: "11" +valset: +- commission: + commission_rates: + max_change_rate: "0.010000000000000000" + max_rate: "0.200000000000000000" + rate: "0.100000000000000000" + update_time: "2021-10-01T05:52:50.380144238Z" + consensus_pubkey: + '@type': /cosmos.crypto.ed25519.PubKey + key: Auxs3865HpB/EfssYOzfqNhEJjzys2Fo6jD5B8tPgC8= + delegator_shares: "10000000.000000000000000000" + description: + details: "" + identity: "" + moniker: myvalidator + security_contact: "" + website: "" + jailed: false + min_self_delegation: "1" + operator_address: cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc + status: BOND_STATUS_BONDED + tokens: "10000000" + unbonding_height: "0" + unbonding_time: "1970-01-01T00:00:00Z" +``` + +##### params + +The `params` command allows users to query values set as staking parameters. + +Usage: + +```bash +simd query staking params [flags] +``` + +Example: + +```bash +simd query staking params +``` + +Example Output: + +```bash +bond_denom: stake +historical_entries: 10000 +max_entries: 7 +max_validators: 50 +unbonding_time: 1814400s +``` + +##### pool + +The `pool` command allows users to query values for amounts stored in the staking pool. + +Usage: + +```bash +simd q staking pool [flags] +``` + +Example: + +```bash +simd q staking pool +``` + +Example Output: + +```bash +bonded_tokens: "10000000" +not_bonded_tokens: "0" +``` + +##### redelegation + +The `redelegation` command allows users to query a redelegation record based on delegator and a source and destination validator address. + +Usage: + +```bash +simd query staking redelegation [delegator-addr] [src-validator-addr] [dst-validator-addr] [flags] +``` + +Example: + +```bash +simd query staking redelegation cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +pagination: null +redelegation_responses: +- entries: + - balance: "50000000" + redelegation_entry: + completion_time: "2021-10-24T20:33:21.960084845Z" + creation_height: 2.382847e+06 + initial_balance: "50000000" + shares_dst: "50000000.000000000000000000" + - balance: "5000000000" + redelegation_entry: + completion_time: "2021-10-25T21:33:54.446846862Z" + creation_height: 2.397271e+06 + initial_balance: "5000000000" + shares_dst: "5000000000.000000000000000000" + redelegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + entries: null + validator_dst_address: cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm + validator_src_address: cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm +``` + +##### redelegations + +The `redelegations` command allows users to query all redelegation records for an individual delegator. + +Usage: + +```bash +simd query staking redelegations [delegator-addr] [flags] +``` + +Example: + +```bash +simd query staking redelegation cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +redelegation_responses: +- entries: + - balance: "50000000" + redelegation_entry: + completion_time: "2021-10-24T20:33:21.960084845Z" + creation_height: 2.382847e+06 + initial_balance: "50000000" + shares_dst: "50000000.000000000000000000" + - balance: "5000000000" + redelegation_entry: + completion_time: "2021-10-25T21:33:54.446846862Z" + creation_height: 2.397271e+06 + initial_balance: "5000000000" + shares_dst: "5000000000.000000000000000000" + redelegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + entries: null + validator_dst_address: cosmosvaloper1uccl5ugxrm7vqlzwqr04pjd320d2fz0z3hc6vm + validator_src_address: cosmosvaloper1zppjyal5emta5cquje8ndkpz0rs046m7zqxrpp +- entries: + - balance: "562770000000" + redelegation_entry: + completion_time: "2021-10-25T21:42:07.336911677Z" + creation_height: 2.39735e+06 + initial_balance: "562770000000" + shares_dst: "562770000000.000000000000000000" + redelegation: + delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + entries: null + validator_dst_address: cosmosvaloper1uccl5ugxrm7vqlzwqr04pjd320d2fz0z3hc6vm + validator_src_address: cosmosvaloper1zppjyal5emta5cquje8ndkpz0rs046m7zqxrpp +``` + +##### redelegations-from + +The `redelegations-from` command allows users to query delegations that are redelegating _from_ a validator. + +Usage: + +```bash +simd query staking redelegations-from [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking redelegations-from cosmosvaloper1y4rzzrgl66eyhzt6gse2k7ej3zgwmngeleucjy +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +redelegation_responses: +- entries: + - balance: "50000000" + redelegation_entry: + completion_time: "2021-10-24T20:33:21.960084845Z" + creation_height: 2.382847e+06 + initial_balance: "50000000" + shares_dst: "50000000.000000000000000000" + - balance: "5000000000" + redelegation_entry: + completion_time: "2021-10-25T21:33:54.446846862Z" + creation_height: 2.397271e+06 + initial_balance: "5000000000" + shares_dst: "5000000000.000000000000000000" + redelegation: + delegator_address: cosmos1pm6e78p4pgn0da365plzl4t56pxy8hwtqp2mph + entries: null + validator_dst_address: cosmosvaloper1uccl5ugxrm7vqlzwqr04pjd320d2fz0z3hc6vm + validator_src_address: cosmosvaloper1y4rzzrgl66eyhzt6gse2k7ej3zgwmngeleucjy +- entries: + - balance: "221000000" + redelegation_entry: + completion_time: "2021-10-05T21:05:45.669420544Z" + creation_height: 2.120693e+06 + initial_balance: "221000000" + shares_dst: "221000000.000000000000000000" + redelegation: + delegator_address: cosmos1zqv8qxy2zgn4c58fz8jt8jmhs3d0attcussrf6 + entries: null + validator_dst_address: cosmosvaloper10mseqwnwtjaqfrwwp2nyrruwmjp6u5jhah4c3y + validator_src_address: cosmosvaloper1y4rzzrgl66eyhzt6gse2k7ej3zgwmngeleucjy +``` + +##### unbonding-delegation + +The `unbonding-delegation` command allows users to query unbonding delegations for an individual delegator on an individual validator. + +Usage: + +```bash +simd query staking unbonding-delegation [delegator-addr] [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking unbonding-delegation cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +entries: +- balance: "52000000" + completion_time: "2021-11-02T11:35:55.391594709Z" + creation_height: "55078" + initial_balance: "52000000" +validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +##### unbonding-delegations + +The `unbonding-delegations` command allows users to query all unbonding-delegations records for one delegator. + +Usage: + +```bash +simd query staking unbonding-delegations [delegator-addr] [flags] +``` + +Example: + +```bash +simd query staking unbonding-delegations cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +unbonding_responses: +- delegator_address: cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p + entries: + - balance: "52000000" + completion_time: "2021-11-02T11:35:55.391594709Z" + creation_height: "55078" + initial_balance: "52000000" + validator_address: cosmosvaloper1t8ehvswxjfn3ejzkjtntcyrqwvmvuknzmvtaaa + +``` + +##### unbonding-delegations-from + +The `unbonding-delegations-from` command allows users to query delegations that are unbonding _from_ a validator. + +Usage: + +```bash +simd query staking unbonding-delegations-from [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking unbonding-delegations-from cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +pagination: + next_key: null + total: "0" +unbonding_responses: +- delegator_address: cosmos1qqq9txnw4c77sdvzx0tkedsafl5s3vk7hn53fn + entries: + - balance: "150000000" + completion_time: "2021-11-01T21:41:13.098141574Z" + creation_height: "46823" + initial_balance: "150000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +- delegator_address: cosmos1peteje73eklqau66mr7h7rmewmt2vt99y24f5z + entries: + - balance: "24000000" + completion_time: "2021-10-31T02:57:18.192280361Z" + creation_height: "21516" + initial_balance: "24000000" + validator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +##### validator + +The `validator` command allows users to query details about an individual validator. + +Usage: + +```bash +simd query staking validator [validator-addr] [flags] +``` + +Example: + +```bash +simd query staking validator cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +``` + +Example Output: + +```bash +commission: + commission_rates: + max_change_rate: "0.020000000000000000" + max_rate: "0.200000000000000000" + rate: "0.050000000000000000" + update_time: "2021-10-01T19:24:52.663191049Z" +consensus_pubkey: + '@type': /cosmos.crypto.ed25519.PubKey + key: sIiexdJdYWn27+7iUHQJDnkp63gq/rzUq1Y+fxoGjXc= +delegator_shares: "32948270000.000000000000000000" +description: + details: Witval is the validator arm from Vitwit. Vitwit is into software consulting + and services business since 2015. We are working closely with Cosmos ecosystem + since 2018. We are also building tools for the ecosystem, Aneka is our explorer + for the cosmos ecosystem. + identity: 51468B615127273A + moniker: Witval + security_contact: "" + website: "" +jailed: false +min_self_delegation: "1" +operator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +status: BOND_STATUS_BONDED +tokens: "32948270000" +unbonding_height: "0" +unbonding_time: "1970-01-01T00:00:00Z" +``` + +##### validators + +The `validators` command allows users to query details about all validators on a network. + +Usage: + +```bash +simd query staking validators [flags] +``` + +Example: + +```bash +simd query staking validators +``` + +Example Output: + +```bash +pagination: + next_key: FPTi7TKAjN63QqZh+BaXn6gBmD5/ + total: "0" +validators: +commission: + commission_rates: + max_change_rate: "0.020000000000000000" + max_rate: "0.200000000000000000" + rate: "0.050000000000000000" + update_time: "2021-10-01T19:24:52.663191049Z" +consensus_pubkey: + '@type': /cosmos.crypto.ed25519.PubKey + key: sIiexdJdYWn27+7iUHQJDnkp63gq/rzUq1Y+fxoGjXc= +delegator_shares: "32948270000.000000000000000000" +description: + details: Witval is the validator arm from Vitwit. Vitwit is into software consulting + and services business since 2015. We are working closely with Cosmos ecosystem + since 2018. We are also building tools for the ecosystem, Aneka is our explorer + for the cosmos ecosystem. + identity: 51468B615127273A + moniker: Witval + security_contact: "" + website: "" + jailed: false + min_self_delegation: "1" + operator_address: cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj + status: BOND_STATUS_BONDED + tokens: "32948270000" + unbonding_height: "0" + unbonding_time: "1970-01-01T00:00:00Z" +- commission: + commission_rates: + max_change_rate: "0.100000000000000000" + max_rate: "0.200000000000000000" + rate: "0.050000000000000000" + update_time: "2021-10-04T18:02:21.446645619Z" + consensus_pubkey: + '@type': /cosmos.crypto.ed25519.PubKey + key: GDNpuKDmCg9GnhnsiU4fCWktuGUemjNfvpCZiqoRIYA= + delegator_shares: "559343421.000000000000000000" + description: + details: Noderunners is a professional validator in POS networks. We have a huge + node running experience, reliable soft and hardware. Our commissions are always + low, our support to delegators is always full. Stake with us and start receiving + your Cosmos rewards now! + identity: 812E82D12FEA3493 + moniker: Noderunners + security_contact: info@noderunners.biz + website: http://noderunners.biz + jailed: false + min_self_delegation: "1" + operator_address: cosmosvaloper1q5ku90atkhktze83j9xjaks2p7uruag5zp6wt7 + status: BOND_STATUS_BONDED + tokens: "559343421" + unbonding_height: "0" + unbonding_time: "1970-01-01T00:00:00Z" +``` + +#### Transactions + +The `tx` commands allows users to interact with the `staking` module. + +```bash +simd tx staking --help +``` + +##### create-validator + +The command `create-validator` allows users to create new validator initialized with a self-delegation to it. + +Usage: + +```bash +simd tx staking create-validator [path/to/validator.json] [flags] +``` + +Example: + +```bash +simd tx staking create-validator /path/to/validator.json \ + --chain-id="name_of_chain_id" \ + --gas="auto" \ + --gas-adjustment="1.2" \ + --gas-prices="0.025stake" \ + --from=mykey +``` + +where `validator.json` contains: + +```json +{ + "pubkey": {"@type":"/cosmos.crypto.ed25519.PubKey","key":"BnbwFpeONLqvWqJb3qaUbL5aoIcW3fSuAp9nT3z5f20="}, + "amount": "1000000stake", + "moniker": "my-moniker", + "website": "https://myweb.site", + "security": "security-contact@gmail.com", + "details": "description of your validator", + "commission-rate": "0.10", + "commission-max-rate": "0.20", + "commission-max-change-rate": "0.01", + "min-self-delegation": "1" +} +``` + +and pubkey can be obtained by using `simd tendermint show-validator` command. + +##### delegate + +The command `delegate` allows users to delegate liquid tokens to a validator. + +Usage: + +```bash +simd tx staking delegate [validator-addr] [amount] [flags] +``` + +Example: + +```bash +simd tx staking delegate cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 1000stake --from mykey +``` + +##### edit-validator + +The command `edit-validator` allows users to edit an existing validator account. + +Usage: + +```bash +simd tx staking edit-validator [flags] +``` + +Example: + +```bash +simd tx staking edit-validator --moniker "new_moniker_name" --website "new_webiste_url" --from mykey +``` + +##### redelegate + +The command `redelegate` allows users to redelegate illiquid tokens from one validator to another. + +Usage: + +```bash +simd tx staking redelegate [src-validator-addr] [dst-validator-addr] [amount] [flags] +``` + +Example: + +```bash +simd tx staking redelegate cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 100stake --from mykey +``` + +##### unbond + +The command `unbond` allows users to unbond shares from a validator. + +Usage: + +```bash +simd tx staking unbond [validator-addr] [amount] [flags] +``` + +Example: + +```bash +simd tx staking unbond cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake --from mykey +``` + +##### cancel unbond + +The command `cancel-unbond` allow users to cancel the unbonding delegation entry and delegate back to the original validator. + +Usage: + +```bash +simd tx staking cancel-unbond [validator-addr] [amount] [creation-height] +``` + +Example: + +```bash +simd tx staking cancel-unbond cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake 123123 --from mykey +``` + + +### gRPC + +A user can query the `staking` module using gRPC endpoints. + +#### Validators + +The `Validators` endpoint queries all validators that match the given status. + +```bash +cosmos.staking.v1beta1.Query/Validators +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.staking.v1beta1.Query/Validators +``` + +Example Output: + +```bash +{ + "validators": [ + { + "operatorAddress": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "consensusPubkey": {"@type":"/cosmos.crypto.ed25519.PubKey","key":"Auxs3865HpB/EfssYOzfqNhEJjzys2Fo6jD5B8tPgC8="}, + "status": "BOND_STATUS_BONDED", + "tokens": "10000000", + "delegatorShares": "10000000000000000000000000", + "description": { + "moniker": "myvalidator" + }, + "unbondingTime": "1970-01-01T00:00:00Z", + "commission": { + "commissionRates": { + "rate": "100000000000000000", + "maxRate": "200000000000000000", + "maxChangeRate": "10000000000000000" + }, + "updateTime": "2021-10-01T05:52:50.380144238Z" + }, + "minSelfDelegation": "1" + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### Validator + +The `Validator` endpoint queries validator information for given validator address. + +```bash +cosmos.staking.v1beta1.Query/Validator +``` + +Example: + +```bash +grpcurl -plaintext -d '{"validator_addr":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/Validator +``` + +Example Output: + +```bash +{ + "validator": { + "operatorAddress": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "consensusPubkey": {"@type":"/cosmos.crypto.ed25519.PubKey","key":"Auxs3865HpB/EfssYOzfqNhEJjzys2Fo6jD5B8tPgC8="}, + "status": "BOND_STATUS_BONDED", + "tokens": "10000000", + "delegatorShares": "10000000000000000000000000", + "description": { + "moniker": "myvalidator" + }, + "unbondingTime": "1970-01-01T00:00:00Z", + "commission": { + "commissionRates": { + "rate": "100000000000000000", + "maxRate": "200000000000000000", + "maxChangeRate": "10000000000000000" + }, + "updateTime": "2021-10-01T05:52:50.380144238Z" + }, + "minSelfDelegation": "1" + } +} +``` + +#### ValidatorDelegations + +The `ValidatorDelegations` endpoint queries delegate information for given validator. + +```bash +cosmos.staking.v1beta1.Query/ValidatorDelegations +``` + +Example: + +```bash +grpcurl -plaintext -d '{"validator_addr":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/ValidatorDelegations +``` + +Example Output: + +```bash +{ + "delegationResponses": [ + { + "delegation": { + "delegatorAddress": "cosmos1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgy3ua5t", + "validatorAddress": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "shares": "10000000000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "10000000" + } + } + ], + "pagination": { + "total": "1" + } +} +``` + +#### ValidatorUnbondingDelegations + +The `ValidatorUnbondingDelegations` endpoint queries delegate information for given validator. + +```bash +cosmos.staking.v1beta1.Query/ValidatorUnbondingDelegations +``` + +Example: + +```bash +grpcurl -plaintext -d '{"validator_addr":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/ValidatorUnbondingDelegations +``` + +Example Output: + +```bash +{ + "unbonding_responses": [ + { + "delegator_address": "cosmos1z3pzzw84d6xn00pw9dy3yapqypfde7vg6965fy", + "validator_address": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "entries": [ + { + "creation_height": "25325", + "completion_time": "2021-10-31T09:24:36.797320636Z", + "initial_balance": "20000000", + "balance": "20000000" + } + ] + }, + { + "delegator_address": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", + "validator_address": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "entries": [ + { + "creation_height": "13100", + "completion_time": "2021-10-30T12:53:02.272266791Z", + "initial_balance": "1000000", + "balance": "1000000" + } + ] + }, + ], + "pagination": { + "next_key": null, + "total": "8" + } +} +``` + +#### Delegation + +The `Delegation` endpoint queries delegate information for given validator delegator pair. + +```bash +cosmos.staking.v1beta1.Query/Delegation +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", validator_addr":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/Delegation +``` + +Example Output: + +```bash +{ + "delegation_response": + { + "delegation": + { + "delegator_address":"cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", + "validator_address":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "shares":"25083119936.000000000000000000" + }, + "balance": + { + "denom":"stake", + "amount":"25083119936" + } + } +} +``` + +#### UnbondingDelegation + +The `UnbondingDelegation` endpoint queries unbonding information for given validator delegator. + +```bash +cosmos.staking.v1beta1.Query/UnbondingDelegation +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", validator_addr":"cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/UnbondingDelegation +``` + +Example Output: + +```bash +{ + "unbond": { + "delegator_address": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", + "validator_address": "cosmosvaloper1rne8lgs98p0jqe82sgt0qr4rdn4hgvmgp9ggcc", + "entries": [ + { + "creation_height": "136984", + "completion_time": "2021-11-08T05:38:47.505593891Z", + "initial_balance": "400000000", + "balance": "400000000" + }, + { + "creation_height": "137005", + "completion_time": "2021-11-08T05:40:53.526196312Z", + "initial_balance": "385000000", + "balance": "385000000" + } + ] + } +} +``` + +#### DelegatorDelegations + +The `DelegatorDelegations` endpoint queries all delegations of a given delegator address. + +```bash +cosmos.staking.v1beta1.Query/DelegatorDelegations +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/DelegatorDelegations +``` + +Example Output: + +```bash +{ + "delegation_responses": [ + {"delegation":{"delegator_address":"cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77","validator_address":"cosmosvaloper1eh5mwu044gd5ntkkc2xgfg8247mgc56fww3vc8","shares":"25083339023.000000000000000000"},"balance":{"denom":"stake","amount":"25083339023"}} + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### DelegatorUnbondingDelegations + +The `DelegatorUnbondingDelegations` endpoint queries all unbonding delegations of a given delegator address. + +```bash +cosmos.staking.v1beta1.Query/DelegatorUnbondingDelegations +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/DelegatorUnbondingDelegations +``` + +Example Output: + +```bash +{ + "unbonding_responses": [ + { + "delegator_address": "cosmos1y8nyfvmqh50p6ldpzljk3yrglppdv3t8phju77", + "validator_address": "cosmosvaloper1sjllsnramtg3ewxqwwrwjxfgc4n4ef9uxyejze", + "entries": [ + { + "creation_height": "136984", + "completion_time": "2021-11-08T05:38:47.505593891Z", + "initial_balance": "400000000", + "balance": "400000000" + }, + { + "creation_height": "137005", + "completion_time": "2021-11-08T05:40:53.526196312Z", + "initial_balance": "385000000", + "balance": "385000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### Redelegations + +The `Redelegations` endpoint queries redelegations of given address. + +```bash +cosmos.staking.v1beta1.Query/Redelegations +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1ld5p7hn43yuh8ht28gm9pfjgj2fctujp2tgwvf", "src_validator_addr" : "cosmosvaloper1j7euyj85fv2jugejrktj540emh9353ltgppc3g", "dst_validator_addr" : "cosmosvaloper1yy3tnegzmkdcm7czzcy3flw5z0zyr9vkkxrfse"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/Redelegations +``` + +Example Output: + +```bash +{ + "redelegation_responses": [ + { + "redelegation": { + "delegator_address": "cosmos1ld5p7hn43yuh8ht28gm9pfjgj2fctujp2tgwvf", + "validator_src_address": "cosmosvaloper1j7euyj85fv2jugejrktj540emh9353ltgppc3g", + "validator_dst_address": "cosmosvaloper1yy3tnegzmkdcm7czzcy3flw5z0zyr9vkkxrfse", + "entries": null + }, + "entries": [ + { + "redelegation_entry": { + "creation_height": 135932, + "completion_time": "2021-11-08T03:52:55.299147901Z", + "initial_balance": "2900000", + "shares_dst": "2900000.000000000000000000" + }, + "balance": "2900000" + } + ] + } + ], + "pagination": null +} +``` + +#### DelegatorValidators + +The `DelegatorValidators` endpoint queries all validators information for given delegator. + +```bash +cosmos.staking.v1beta1.Query/DelegatorValidators +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1ld5p7hn43yuh8ht28gm9pfjgj2fctujp2tgwvf"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/DelegatorValidators +``` + +Example Output: + +```bash +{ + "validators": [ + { + "operator_address": "cosmosvaloper1eh5mwu044gd5ntkkc2xgfg8247mgc56fww3vc8", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "UPwHWxH1zHJWGOa/m6JB3f5YjHMvPQPkVbDqqi+U7Uw=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "347260647559", + "delegator_shares": "347260647559.000000000000000000", + "description": { + "moniker": "BouBouNode", + "identity": "", + "website": "https://boubounode.com", + "security_contact": "", + "details": "AI-based Validator. #1 AI Validator on Game of Stakes. Fairly priced. Don't trust (humans), verify. Made with BouBou love." + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.061000000000000000", + "max_rate": "0.300000000000000000", + "max_change_rate": "0.150000000000000000" + }, + "update_time": "2021-10-01T15:00:00Z" + }, + "min_self_delegation": "1" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### DelegatorValidator + +The `DelegatorValidator` endpoint queries validator information for given delegator validator + +```bash +cosmos.staking.v1beta1.Query/DelegatorValidator +``` + +Example: + +```bash +grpcurl -plaintext \ +-d '{"delegator_addr": "cosmos1eh5mwu044gd5ntkkc2xgfg8247mgc56f3n8rr7", "validator_addr": "cosmosvaloper1eh5mwu044gd5ntkkc2xgfg8247mgc56fww3vc8"}' \ +localhost:9090 cosmos.staking.v1beta1.Query/DelegatorValidator +``` + +Example Output: + +```bash +{ + "validator": { + "operator_address": "cosmosvaloper1eh5mwu044gd5ntkkc2xgfg8247mgc56fww3vc8", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "UPwHWxH1zHJWGOa/m6JB3f5YjHMvPQPkVbDqqi+U7Uw=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "347262754841", + "delegator_shares": "347262754841.000000000000000000", + "description": { + "moniker": "BouBouNode", + "identity": "", + "website": "https://boubounode.com", + "security_contact": "", + "details": "AI-based Validator. #1 AI Validator on Game of Stakes. Fairly priced. Don't trust (humans), verify. Made with BouBou love." + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.061000000000000000", + "max_rate": "0.300000000000000000", + "max_change_rate": "0.150000000000000000" + }, + "update_time": "2021-10-01T15:00:00Z" + }, + "min_self_delegation": "1" + } +} +``` + +#### HistoricalInfo + +```bash +cosmos.staking.v1beta1.Query/HistoricalInfo +``` + +Example: + +```bash +grpcurl -plaintext -d '{"height" : 1}' localhost:9090 cosmos.staking.v1beta1.Query/HistoricalInfo +``` + +Example Output: + +```bash +{ + "hist": { + "header": { + "version": { + "block": "11", + "app": "0" + }, + "chain_id": "simd-1", + "height": "140142", + "time": "2021-10-11T10:56:29.720079569Z", + "last_block_id": { + "hash": "9gri/4LLJUBFqioQ3NzZIP9/7YHR9QqaM6B2aJNQA7o=", + "part_set_header": { + "total": 1, + "hash": "Hk1+C864uQkl9+I6Zn7IurBZBKUevqlVtU7VqaZl1tc=" + } + }, + "last_commit_hash": "VxrcS27GtvGruS3I9+AlpT7udxIT1F0OrRklrVFSSKc=", + "data_hash": "80BjOrqNYUOkTnmgWyz9AQ8n7SoEmPVi4QmAe8RbQBY=", + "validators_hash": "95W49n2hw8RWpr1GPTAO5MSPi6w6Wjr3JjjS7AjpBho=", + "next_validators_hash": "95W49n2hw8RWpr1GPTAO5MSPi6w6Wjr3JjjS7AjpBho=", + "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=", + "app_hash": "ZZaxnSY3E6Ex5Bvkm+RigYCK82g8SSUL53NymPITeOE=", + "last_results_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "proposer_address": "aH6dO428B+ItuoqPq70efFHrSMY=" + }, + "valset": [ + { + "operator_address": "cosmosvaloper196ax4vc0lwpxndu9dyhvca7jhxp70rmcqcnylw", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "/O7BtNW0pafwfvomgR4ZnfldwPXiFfJs9mHg3gwfv5Q=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "1426045203613", + "delegator_shares": "1426045203613.000000000000000000", + "description": { + "moniker": "SG-1", + "identity": "48608633F99D1B60", + "website": "https://sg-1.online", + "security_contact": "", + "details": "SG-1 - your favorite validator on Witval. We offer 100% Soft Slash protection." + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.037500000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.030000000000000000" + }, + "update_time": "2021-10-01T15:00:00Z" + }, + "min_self_delegation": "1" + } + ] + } +} + +``` + +#### Pool + +The `Pool` endpoint queries the pool information. + +```bash +cosmos.staking.v1beta1.Query/Pool +``` + +Example: + +```bash +grpcurl -plaintext -d localhost:9090 cosmos.staking.v1beta1.Query/Pool +``` + +Example Output: + +```bash +{ + "pool": { + "not_bonded_tokens": "369054400189", + "bonded_tokens": "15657192425623" + } +} +``` + +#### Params + +The `Params` endpoint queries the pool information. + +```bash +cosmos.staking.v1beta1.Query/Params +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.staking.v1beta1.Query/Params +``` + +Example Output: + +```bash +{ + "params": { + "unbondingTime": "1814400s", + "maxValidators": 100, + "maxEntries": 7, + "historicalEntries": 10000, + "bondDenom": "stake" + } +} +``` + +### REST + +A user can query the `staking` module using REST endpoints. + +#### DelegatorDelegations + +The `DelegtaorDelegations` REST endpoint queries all delegations of a given delegator address. + +```bash +/cosmos/staking/v1beta1/delegations/{delegatorAddr} +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/delegations/cosmos1vcs68xf2tnqes5tg0khr0vyevm40ff6zdxatp5" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "delegation_responses": [ + { + "delegation": { + "delegator_address": "cosmos1vcs68xf2tnqes5tg0khr0vyevm40ff6zdxatp5", + "validator_address": "cosmosvaloper1quqxfrxkycr0uzt4yk0d57tcq3zk7srm7sm6r8", + "shares": "256250000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "256250000" + } + }, + { + "delegation": { + "delegator_address": "cosmos1vcs68xf2tnqes5tg0khr0vyevm40ff6zdxatp5", + "validator_address": "cosmosvaloper194v8uwee2fvs2s8fa5k7j03ktwc87h5ym39jfv", + "shares": "255150000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "255150000" + } + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` + +#### Redelegations + +The `Redelegations` REST endpoint queries redelegations of given address. + +```bash +/cosmos/staking/v1beta1/delegators/{delegatorAddr}/redelegations +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/delegators/cosmos1thfntksw0d35n2tkr0k8v54fr8wxtxwxl2c56e/redelegations?srcValidatorAddr=cosmosvaloper1lzhlnpahvznwfv4jmay2tgaha5kmz5qx4cuznf&dstValidatorAddr=cosmosvaloper1vq8tw77kp8lvxq9u3c8eeln9zymn68rng8pgt4" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "redelegation_responses": [ + { + "redelegation": { + "delegator_address": "cosmos1thfntksw0d35n2tkr0k8v54fr8wxtxwxl2c56e", + "validator_src_address": "cosmosvaloper1lzhlnpahvznwfv4jmay2tgaha5kmz5qx4cuznf", + "validator_dst_address": "cosmosvaloper1vq8tw77kp8lvxq9u3c8eeln9zymn68rng8pgt4", + "entries": null + }, + "entries": [ + { + "redelegation_entry": { + "creation_height": 151523, + "completion_time": "2021-11-09T06:03:25.640682116Z", + "initial_balance": "200000000", + "shares_dst": "200000000.000000000000000000" + }, + "balance": "200000000" + } + ] + } + ], + "pagination": null +} +``` + +#### DelegatorUnbondingDelegations + +The `DelegatorUnbondingDelegations` REST endpoint queries all unbonding delegations of a given delegator address. + +```bash +/cosmos/staking/v1beta1/delegators/{delegatorAddr}/unbonding_delegations +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/delegators/cosmos1nxv42u3lv642q0fuzu2qmrku27zgut3n3z7lll/unbonding_delegations" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "unbonding_responses": [ + { + "delegator_address": "cosmos1nxv42u3lv642q0fuzu2qmrku27zgut3n3z7lll", + "validator_address": "cosmosvaloper1e7mvqlz50ch6gw4yjfemsc069wfre4qwmw53kq", + "entries": [ + { + "creation_height": "2442278", + "completion_time": "2021-10-12T10:59:03.797335857Z", + "initial_balance": "50000000000", + "balance": "50000000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### DelegatorValidators + +The `DelegatorValidators` REST endpoint queries all validators information for given delegator address. + +```bash +/cosmos/staking/v1beta1/delegators/{delegatorAddr}/validators +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/delegators/cosmos1xwazl8ftks4gn00y5x3c47auquc62ssune9ppv/validators" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "validators": [ + { + "operator_address": "cosmosvaloper1xwazl8ftks4gn00y5x3c47auquc62ssuvynw64", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "5v4n3px3PkfNnKflSgepDnsMQR1hiNXnqOC11Y72/PQ=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "21592843799", + "delegator_shares": "21592843799.000000000000000000", + "description": { + "moniker": "jabbey", + "identity": "", + "website": "https://twitter.com/JoeAbbey", + "security_contact": "", + "details": "just another dad in the cosmos" + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.100000000000000000" + }, + "update_time": "2021-10-09T19:03:54.984821705Z" + }, + "min_self_delegation": "1" + } + ], + "pagination": { + "next_key": null, + "total": "1" + } +} +``` + +#### DelegatorValidator + +The `DelegatorValidator` REST endpoint queries validator information for given delegator validator pair. + +```bash +/cosmos/staking/v1beta1/delegators/{delegatorAddr}/validators/{validatorAddr} +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/delegators/cosmos1xwazl8ftks4gn00y5x3c47auquc62ssune9ppv/validators/cosmosvaloper1xwazl8ftks4gn00y5x3c47auquc62ssuvynw64" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "validator": { + "operator_address": "cosmosvaloper1xwazl8ftks4gn00y5x3c47auquc62ssuvynw64", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "5v4n3px3PkfNnKflSgepDnsMQR1hiNXnqOC11Y72/PQ=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "21592843799", + "delegator_shares": "21592843799.000000000000000000", + "description": { + "moniker": "jabbey", + "identity": "", + "website": "https://twitter.com/JoeAbbey", + "security_contact": "", + "details": "just another dad in the cosmos" + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.100000000000000000" + }, + "update_time": "2021-10-09T19:03:54.984821705Z" + }, + "min_self_delegation": "1" + } +} +``` + +#### HistoricalInfo + +The `HistoricalInfo` REST endpoint queries the historical information for given height. + +```bash +/cosmos/staking/v1beta1/historical_info/{height} +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/historical_info/153332" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "hist": { + "header": { + "version": { + "block": "11", + "app": "0" + }, + "chain_id": "cosmos-1", + "height": "153332", + "time": "2021-10-12T09:05:35.062230221Z", + "last_block_id": { + "hash": "NX8HevR5khb7H6NGKva+jVz7cyf0skF1CrcY9A0s+d8=", + "part_set_header": { + "total": 1, + "hash": "zLQ2FiKM5tooL3BInt+VVfgzjlBXfq0Hc8Iux/xrhdg=" + } + }, + "last_commit_hash": "P6IJrK8vSqU3dGEyRHnAFocoDGja0bn9euLuy09s350=", + "data_hash": "eUd+6acHWrNXYju8Js449RJ99lOYOs16KpqQl4SMrEM=", + "validators_hash": "mB4pravvMsJKgi+g8aYdSeNlt0kPjnRFyvtAQtaxcfw=", + "next_validators_hash": "mB4pravvMsJKgi+g8aYdSeNlt0kPjnRFyvtAQtaxcfw=", + "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=", + "app_hash": "fuELArKRK+CptnZ8tu54h6xEleSWenHNmqC84W866fU=", + "last_results_hash": "p/BPexV4LxAzlVcPRvW+lomgXb6Yze8YLIQUo/4Kdgc=", + "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "proposer_address": "G0MeY8xQx7ooOsni8KE/3R/Ib3Q=" + }, + "valset": [ + { + "operator_address": "cosmosvaloper196ax4vc0lwpxndu9dyhvca7jhxp70rmcqcnylw", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "/O7BtNW0pafwfvomgR4ZnfldwPXiFfJs9mHg3gwfv5Q=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "1416521659632", + "delegator_shares": "1416521659632.000000000000000000", + "description": { + "moniker": "SG-1", + "identity": "48608633F99D1B60", + "website": "https://sg-1.online", + "security_contact": "", + "details": "SG-1 - your favorite validator on cosmos. We offer 100% Soft Slash protection." + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.037500000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.030000000000000000" + }, + "update_time": "2021-10-01T15:00:00Z" + }, + "min_self_delegation": "1" + }, + { + "operator_address": "cosmosvaloper1t8ehvswxjfn3ejzkjtntcyrqwvmvuknzmvtaaa", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "uExZyjNLtr2+FFIhNDAMcQ8+yTrqE7ygYTsI7khkA5Y=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "1348298958808", + "delegator_shares": "1348298958808.000000000000000000", + "description": { + "moniker": "Cosmostation", + "identity": "AE4C403A6E7AA1AC", + "website": "https://www.cosmostation.io", + "security_contact": "admin@stamper.network", + "details": "Cosmostation validator node. Delegate your tokens and Start Earning Staking Rewards" + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.050000000000000000", + "max_rate": "1.000000000000000000", + "max_change_rate": "0.200000000000000000" + }, + "update_time": "2021-10-01T15:06:38.821314287Z" + }, + "min_self_delegation": "1" + } + ] + } +} +``` + +#### Parameters + +The `Parameters` REST endpoint queries the staking parameters. + +```bash +/cosmos/staking/v1beta1/params +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/params" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "params": { + "unbonding_time": "2419200s", + "max_validators": 100, + "max_entries": 7, + "historical_entries": 10000, + "bond_denom": "stake" + } +} +``` + +#### Pool + +The `Pool` REST endpoint queries the pool information. + +```bash +/cosmos/staking/v1beta1/pool +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/pool" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "pool": { + "not_bonded_tokens": "432805737458", + "bonded_tokens": "15783637712645" + } +} +``` + +#### Validators + +The `Validators` REST endpoint queries all validators that match the given status. + +```bash +/cosmos/staking/v1beta1/validators +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/validators" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "validators": [ + { + "operator_address": "cosmosvaloper1q3jsx9dpfhtyqqgetwpe5tmk8f0ms5qywje8tw", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "N7BPyek2aKuNZ0N/8YsrqSDhGZmgVaYUBuddY8pwKaE=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "383301887799", + "delegator_shares": "383301887799.000000000000000000", + "description": { + "moniker": "SmartNodes", + "identity": "D372724899D1EDC8", + "website": "https://smartnodes.co", + "security_contact": "", + "details": "Earn Rewards with Crypto Staking & Node Deployment" + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.050000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.100000000000000000" + }, + "update_time": "2021-10-01T15:51:31.596618510Z" + }, + "min_self_delegation": "1" + }, + { + "operator_address": "cosmosvaloper1q5ku90atkhktze83j9xjaks2p7uruag5zp6wt7", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "GDNpuKDmCg9GnhnsiU4fCWktuGUemjNfvpCZiqoRIYA=" + }, + "jailed": false, + "status": "BOND_STATUS_UNBONDING", + "tokens": "1017819654", + "delegator_shares": "1017819654.000000000000000000", + "description": { + "moniker": "Noderunners", + "identity": "812E82D12FEA3493", + "website": "http://noderunners.biz", + "security_contact": "info@noderunners.biz", + "details": "Noderunners is a professional validator in POS networks. We have a huge node running experience, reliable soft and hardware. Our commissions are always low, our support to delegators is always full. Stake with us and start receiving your cosmos rewards now!" + }, + "unbonding_height": "147302", + "unbonding_time": "2021-11-08T22:58:53.718662452Z", + "commission": { + "commission_rates": { + "rate": "0.050000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.100000000000000000" + }, + "update_time": "2021-10-04T18:02:21.446645619Z" + }, + "min_self_delegation": "1" + } + ], + "pagination": { + "next_key": "FONDBFkE4tEEf7yxWWKOD49jC2NK", + "total": "2" + } +} +``` + +#### Validator + +The `Validator` REST endpoint queries validator information for given validator address. + +```bash +/cosmos/staking/v1beta1/validators/{validatorAddr} +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/validators/cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "validator": { + "operator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "consensus_pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "sIiexdJdYWn27+7iUHQJDnkp63gq/rzUq1Y+fxoGjXc=" + }, + "jailed": false, + "status": "BOND_STATUS_BONDED", + "tokens": "33027900000", + "delegator_shares": "33027900000.000000000000000000", + "description": { + "moniker": "Witval", + "identity": "51468B615127273A", + "website": "", + "security_contact": "", + "details": "Witval is the validator arm from Vitwit. Vitwit is into software consulting and services business since 2015. We are working closely with Cosmos ecosystem since 2018. We are also building tools for the ecosystem, Aneka is our explorer for the cosmos ecosystem." + }, + "unbonding_height": "0", + "unbonding_time": "1970-01-01T00:00:00Z", + "commission": { + "commission_rates": { + "rate": "0.050000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.020000000000000000" + }, + "update_time": "2021-10-01T19:24:52.663191049Z" + }, + "min_self_delegation": "1" + } +} +``` + +#### ValidatorDelegations + +The `ValidatorDelegations` REST endpoint queries delegate information for given validator. + +```bash +/cosmos/staking/v1beta1/validators/{validatorAddr}/delegations +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/staking/v1beta1/validators/cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q/delegations" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "delegation_responses": [ + { + "delegation": { + "delegator_address": "cosmos190g5j8aszqhvtg7cprmev8xcxs6csra7xnk3n3", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "31000000000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "31000000000" + } + }, + { + "delegation": { + "delegator_address": "cosmos1ddle9tczl87gsvmeva3c48nenyng4n56qwq4ee", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "628470000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "628470000" + } + }, + { + "delegation": { + "delegator_address": "cosmos10fdvkczl76m040smd33lh9xn9j0cf26kk4s2nw", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "838120000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "838120000" + } + }, + { + "delegation": { + "delegator_address": "cosmos1n8f5fknsv2yt7a8u6nrx30zqy7lu9jfm0t5lq8", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "500000000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "500000000" + } + }, + { + "delegation": { + "delegator_address": "cosmos16msryt3fqlxtvsy8u5ay7wv2p8mglfg9hrek2e", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "61310000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "61310000" + } + } + ], + "pagination": { + "next_key": null, + "total": "5" + } +} +``` + +#### Delegation + +The `Delegation` REST endpoint queries delegate information for given validator delegator pair. + +```bash +/cosmos/staking/v1beta1/validators/{validatorAddr}/delegations/{delegatorAddr} +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/validators/cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q/delegations/cosmos1n8f5fknsv2yt7a8u6nrx30zqy7lu9jfm0t5lq8" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "delegation_response": { + "delegation": { + "delegator_address": "cosmos1n8f5fknsv2yt7a8u6nrx30zqy7lu9jfm0t5lq8", + "validator_address": "cosmosvaloper16msryt3fqlxtvsy8u5ay7wv2p8mglfg9g70e3q", + "shares": "500000000.000000000000000000" + }, + "balance": { + "denom": "stake", + "amount": "500000000" + } + } +} +``` + +#### UnbondingDelegation + +The `UnbondingDelegation` REST endpoint queries unbonding information for given validator delegator pair. + +```bash +/cosmos/staking/v1beta1/validators/{validatorAddr}/delegations/{delegatorAddr}/unbonding_delegation +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/validators/cosmosvaloper13v4spsah85ps4vtrw07vzea37gq5la5gktlkeu/delegations/cosmos1ze2ye5u5k3qdlexvt2e0nn0508p04094ya0qpm/unbonding_delegation" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "unbond": { + "delegator_address": "cosmos1ze2ye5u5k3qdlexvt2e0nn0508p04094ya0qpm", + "validator_address": "cosmosvaloper13v4spsah85ps4vtrw07vzea37gq5la5gktlkeu", + "entries": [ + { + "creation_height": "153687", + "completion_time": "2021-11-09T09:41:18.352401903Z", + "initial_balance": "525111", + "balance": "525111" + } + ] + } +} +``` + +#### ValidatorUnbondingDelegations + +The `ValidatorUnbondingDelegations` REST endpoint queries unbonding delegations of a validator. + +```bash +/cosmos/staking/v1beta1/validators/{validatorAddr}/unbonding_delegations +``` + +Example: + +```bash +curl -X GET \ +"http://localhost:1317/cosmos/staking/v1beta1/validators/cosmosvaloper13v4spsah85ps4vtrw07vzea37gq5la5gktlkeu/unbonding_delegations" \ +-H "accept: application/json" +``` + +Example Output: + +```bash +{ + "unbonding_responses": [ + { + "delegator_address": "cosmos1q9snn84jfrd9ge8t46kdcggpe58dua82vnj7uy", + "validator_address": "cosmosvaloper13v4spsah85ps4vtrw07vzea37gq5la5gktlkeu", + "entries": [ + { + "creation_height": "90998", + "completion_time": "2021-11-05T00:14:37.005841058Z", + "initial_balance": "24000000", + "balance": "24000000" + } + ] + }, + { + "delegator_address": "cosmos1qf36e6wmq9h4twhdvs6pyq9qcaeu7ye0s3dqq2", + "validator_address": "cosmosvaloper13v4spsah85ps4vtrw07vzea37gq5la5gktlkeu", + "entries": [ + { + "creation_height": "47478", + "completion_time": "2021-11-01T22:47:26.714116854Z", + "initial_balance": "8000000", + "balance": "8000000" + } + ] + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` diff --git a/versioned_docs/version-0.47/integrate/modules/upgrade/README.md b/versioned_docs/version-0.47/integrate/modules/upgrade/README.md new file mode 100644 index 000000000..d1be1b2c8 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/modules/upgrade/README.md @@ -0,0 +1,619 @@ +--- +sidebar_position: 1 +--- + +# `x/upgrade` + +## Abstract + +`x/upgrade` is an implementation of a Cosmos SDK module that facilitates smoothly +upgrading a live Cosmos chain to a new (breaking) software version. It accomplishes this by +providing a `BeginBlocker` hook that prevents the blockchain state machine from +proceeding once a pre-defined upgrade block height has been reached. + +The module does not prescribe anything regarding how governance decides to do an +upgrade, but just the mechanism for coordinating the upgrade safely. Without software +support for upgrades, upgrading a live chain is risky because all of the validators +need to pause their state machines at exactly the same point in the process. If +this is not done correctly, there can be state inconsistencies which are hard to +recover from. + +* [Concepts](#concepts) +* [State](#state) +* [Events](#events) +* [Client](#client) + * [CLI](#cli) + * [REST](#rest) + * [gRPC](#grpc) +* [Resources](#resources) + +## Concepts + +### Plan + +The `x/upgrade` module defines a `Plan` type in which a live upgrade is scheduled +to occur. A `Plan` can be scheduled at a specific block height. +A `Plan` is created once a (frozen) release candidate along with an appropriate upgrade +`Handler` (see below) is agreed upon, where the `Name` of a `Plan` corresponds to a +specific `Handler`. Typically, a `Plan` is created through a governance proposal +process, where if voted upon and passed, will be scheduled. The `Info` of a `Plan` +may contain various metadata about the upgrade, typically application specific +upgrade info to be included on-chain such as a git commit that validators could +automatically upgrade to. + +#### Sidecar Process + +If an operator running the application binary also runs a sidecar process to assist +in the automatic download and upgrade of a binary, the `Info` allows this process to +be seamless. This tool is [Cosmovisor](https://github.com/cosmos/cosmos-sdk/tree/main/tools/cosmovisor#readme). + +```go +type Plan struct { + Name string + Height int64 + Info string +} +``` + +### Handler + +The `x/upgrade` module facilitates upgrading from major version X to major version Y. To +accomplish this, node operators must first upgrade their current binary to a new +binary that has a corresponding `Handler` for the new version Y. It is assumed that +this version has fully been tested and approved by the community at large. This +`Handler` defines what state migrations need to occur before the new binary Y +can successfully run the chain. Naturally, this `Handler` is application specific +and not defined on a per-module basis. Registering a `Handler` is done via +`Keeper#SetUpgradeHandler` in the application. + +```go +type UpgradeHandler func(Context, Plan, VersionMap) (VersionMap, error) +``` + +During each `EndBlock` execution, the `x/upgrade` module checks if there exists a +`Plan` that should execute (is scheduled at that height). If so, the corresponding +`Handler` is executed. If the `Plan` is expected to execute but no `Handler` is registered +or if the binary was upgraded too early, the node will gracefully panic and exit. + +### StoreLoader + +The `x/upgrade` module also facilitates store migrations as part of the upgrade. The +`StoreLoader` sets the migrations that need to occur before the new binary can +successfully run the chain. This `StoreLoader` is also application specific and +not defined on a per-module basis. Registering this `StoreLoader` is done via +`app#SetStoreLoader` in the application. + +```go +func UpgradeStoreLoader (upgradeHeight int64, storeUpgrades *store.StoreUpgrades) baseapp.StoreLoader +``` + +If there's a planned upgrade and the upgrade height is reached, the old binary writes `Plan` to the disk before panicking. + +This information is critical to ensure the `StoreUpgrades` happens smoothly at correct height and +expected upgrade. It eliminiates the chances for the new binary to execute `StoreUpgrades` multiple +times everytime on restart. Also if there are multiple upgrades planned on same height, the `Name` +will ensure these `StoreUpgrades` takes place only in planned upgrade handler. + +### Proposal + +Typically, a `Plan` is proposed and submitted through governance via a proposal +containing a `MsgSoftwareUpgrade` message. +This proposal prescribes to the standard governance process. If the proposal passes, +the `Plan`, which targets a specific `Handler`, is persisted and scheduled. The +upgrade can be delayed or hastened by updating the `Plan.Height` in a new proposal. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L29-L41 +``` + +#### Cancelling Upgrade Proposals + +Upgrade proposals can be cancelled. There exists a gov-enabled `MsgCancelUpgrade` +message type, which can be embedded in a proposal, voted on and, if passed, will +remove the scheduled upgrade `Plan`. +Of course this requires that the upgrade was known to be a bad idea well before the +upgrade itself, to allow time for a vote. + +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L48-L57 +``` + +If such a possibility is desired, the upgrade height is to be +`2 * (VotingPeriod + DepositPeriod) + (SafetyDelta)` from the beginning of the +upgrade proposal. The `SafetyDelta` is the time available from the success of an +upgrade proposal and the realization it was a bad idea (due to external social consensus). + +A `MsgCancelUpgrade` proposal can also be made while the original +`MsgSoftwareUpgrade` proposal is still being voted upon, as long as the `VotingPeriod` +ends after the `MsgSoftwareUpgrade` proposal. + +## State + +The internal state of the `x/upgrade` module is relatively minimal and simple. The +state contains the currently active upgrade `Plan` (if one exists) by key +`0x0` and if a `Plan` is marked as "done" by key `0x1`. The state +contains the consensus versions of all app modules in the application. The versions +are stored as big endian `uint64`, and can be accessed with prefix `0x2` appended +by the corresponding module name of type `string`. The state maintains a +`Protocol Version` which can be accessed by key `0x3`. + +* Plan: `0x0 -> Plan` +* Done: `0x1 | byte(plan name) -> BigEndian(Block Height)` +* ConsensusVersion: `0x2 | byte(module name) -> BigEndian(Module Consensus Version)` +* ProtocolVersion: `0x3 -> BigEndian(Protocol Version)` + +The `x/upgrade` module contains no genesis state. + +## Events + +The `x/upgrade` does not emit any events by itself. Any and all proposal related +events are emitted through the `x/gov` module. + +## Client + +### CLI + +A user can query and interact with the `upgrade` module using the CLI. + +#### Query + +The `query` commands allow users to query `upgrade` state. + +```bash +simd query upgrade --help +``` + +##### applied + +The `applied` command allows users to query the block header for height at which a completed upgrade was applied. + +```bash +simd query upgrade applied [upgrade-name] [flags] +``` + +If upgrade-name was previously executed on the chain, this returns the header for the block at which it was applied. +This helps a client determine which binary was valid over a given range of blocks, as well as more context to understand past migrations. + +Example: + +```bash +simd query upgrade applied "test-upgrade" +``` + +Example Output: + +```bash +"block_id": { + "hash": "A769136351786B9034A5F196DC53F7E50FCEB53B48FA0786E1BFC45A0BB646B5", + "parts": { + "total": 1, + "hash": "B13CBD23011C7480E6F11BE4594EE316548648E6A666B3575409F8F16EC6939E" + } + }, + "block_size": "7213", + "header": { + "version": { + "block": "11" + }, + "chain_id": "testnet-2", + "height": "455200", + "time": "2021-04-10T04:37:57.085493838Z", + "last_block_id": { + "hash": "0E8AD9309C2DC411DF98217AF59E044A0E1CCEAE7C0338417A70338DF50F4783", + "parts": { + "total": 1, + "hash": "8FE572A48CD10BC2CBB02653CA04CA247A0F6830FF19DC972F64D339A355E77D" + } + }, + "last_commit_hash": "DE890239416A19E6164C2076B837CC1D7F7822FC214F305616725F11D2533140", + "data_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", + "validators_hash": "A31047ADE54AE9072EE2A12FF260A8990BA4C39F903EAF5636B50D58DBA72582", + "next_validators_hash": "A31047ADE54AE9072EE2A12FF260A8990BA4C39F903EAF5636B50D58DBA72582", + "consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F", + "app_hash": "28ECC486AFC332BA6CC976706DBDE87E7D32441375E3F10FD084CD4BAF0DA021", + "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", + "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", + "proposer_address": "2ABC4854B1A1C5AA8403C4EA853A81ACA901CC76" + }, + "num_txs": "0" +} +``` + +##### module versions + +The `module_versions` command gets a list of module names and their respective consensus versions. + +Following the command with a specific module name will return only +that module's information. + +```bash +simd query upgrade module_versions [optional module_name] [flags] +``` + +Example: + +```bash +simd query upgrade module_versions +``` + +Example Output: + +```bash +module_versions: +- name: auth + version: "2" +- name: authz + version: "1" +- name: bank + version: "2" +- name: crisis + version: "1" +- name: distribution + version: "2" +- name: evidence + version: "1" +- name: feegrant + version: "1" +- name: genutil + version: "1" +- name: gov + version: "2" +- name: ibc + version: "2" +- name: mint + version: "1" +- name: params + version: "1" +- name: slashing + version: "2" +- name: staking + version: "2" +- name: transfer + version: "1" +- name: upgrade + version: "1" +- name: vesting + version: "1" +``` + +Example: + +```bash +regen query upgrade module_versions ibc +``` + +Example Output: + +```bash +module_versions: +- name: ibc + version: "2" +``` + +##### plan + +The `plan` command gets the currently scheduled upgrade plan, if one exists. + +```bash +regen query upgrade plan [flags] +``` + +Example: + +```bash +simd query upgrade plan +``` + +Example Output: + +```bash +height: "130" +info: "" +name: test-upgrade +time: "0001-01-01T00:00:00Z" +upgraded_client_state: null +``` + +#### Transactions + +The upgrade module supports the following transactions: + +* `software-proposal` - submits an upgrade proposal: + +```bash +simd tx upgrade software-upgrade v2 --title="Test Proposal" --summary="testing" --deposit="100000000stake" --upgrade-height 1000000 \ +--upgrade-info '{ "binaries": { "linux/amd64":"https://example.com/simd.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" } }' --from cosmos1.. +``` + +* `cancel-software-upgrade` - cancels a previously submitted upgrade proposal: + +```bash +simd tx upgrade cancel-software-upgrade --title="Test Proposal" --summary="testing" --deposit="100000000stake" --from cosmos1.. +``` + +### REST + +A user can query the `upgrade` module using REST endpoints. + +#### Applied Plan + +`AppliedPlan` queries a previously applied upgrade plan by its name. + +```bash +/cosmos/upgrade/v1beta1/applied_plan/{name} +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/applied_plan/v2.0-upgrade" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "height": "30" +} +``` + +#### Current Plan + +`CurrentPlan` queries the current upgrade plan. + +```bash +/cosmos/upgrade/v1beta1/current_plan +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/current_plan" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "plan": "v2.1-upgrade" +} +``` + +#### Module versions + +`ModuleVersions` queries the list of module versions from state. + +```bash +/cosmos/upgrade/v1beta1/module_versions +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/module_versions" -H "accept: application/json" +``` + +Example Output: + +```bash +{ + "module_versions": [ + { + "name": "auth", + "version": "2" + }, + { + "name": "authz", + "version": "1" + }, + { + "name": "bank", + "version": "2" + }, + { + "name": "crisis", + "version": "1" + }, + { + "name": "distribution", + "version": "2" + }, + { + "name": "evidence", + "version": "1" + }, + { + "name": "feegrant", + "version": "1" + }, + { + "name": "genutil", + "version": "1" + }, + { + "name": "gov", + "version": "2" + }, + { + "name": "ibc", + "version": "2" + }, + { + "name": "mint", + "version": "1" + }, + { + "name": "params", + "version": "1" + }, + { + "name": "slashing", + "version": "2" + }, + { + "name": "staking", + "version": "2" + }, + { + "name": "transfer", + "version": "1" + }, + { + "name": "upgrade", + "version": "1" + }, + { + "name": "vesting", + "version": "1" + } + ] +} +``` + +### gRPC + +A user can query the `upgrade` module using gRPC endpoints. + +#### Applied Plan + +`AppliedPlan` queries a previously applied upgrade plan by its name. + +```bash +cosmos.upgrade.v1beta1.Query/AppliedPlan +``` + +Example: + +```bash +grpcurl -plaintext \ + -d '{"name":"v2.0-upgrade"}' \ + localhost:9090 \ + cosmos.upgrade.v1beta1.Query/AppliedPlan +``` + +Example Output: + +```bash +{ + "height": "30" +} +``` + +#### Current Plan + +`CurrentPlan` queries the current upgrade plan. + +```bash +cosmos.upgrade.v1beta1.Query/CurrentPlan +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/CurrentPlan +``` + +Example Output: + +```bash +{ + "plan": "v2.1-upgrade" +} +``` + +#### Module versions + +`ModuleVersions` queries the list of module versions from state. + +```bash +cosmos.upgrade.v1beta1.Query/ModuleVersions +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/ModuleVersions +``` + +Example Output: + +```bash +{ + "module_versions": [ + { + "name": "auth", + "version": "2" + }, + { + "name": "authz", + "version": "1" + }, + { + "name": "bank", + "version": "2" + }, + { + "name": "crisis", + "version": "1" + }, + { + "name": "distribution", + "version": "2" + }, + { + "name": "evidence", + "version": "1" + }, + { + "name": "feegrant", + "version": "1" + }, + { + "name": "genutil", + "version": "1" + }, + { + "name": "gov", + "version": "2" + }, + { + "name": "ibc", + "version": "2" + }, + { + "name": "mint", + "version": "1" + }, + { + "name": "params", + "version": "1" + }, + { + "name": "slashing", + "version": "2" + }, + { + "name": "staking", + "version": "2" + }, + { + "name": "transfer", + "version": "1" + }, + { + "name": "upgrade", + "version": "1" + }, + { + "name": "vesting", + "version": "1" + } + ] +} +``` + +## Resources + +A list of (external) resources to learn more about the `x/upgrade` module. + +* [Cosmos Dev Series: Cosmos Blockchain Upgrade](https://medium.com/web3-surfers/cosmos-dev-series-cosmos-sdk-based-blockchain-upgrade-b5e99181554c) - The blog post that explains how software upgrades work in detail. diff --git a/versioned_docs/version-0.47/integrate/rfc/PROCESS.md b/versioned_docs/version-0.47/integrate/rfc/PROCESS.md new file mode 100644 index 000000000..71b0c7ce7 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/rfc/PROCESS.md @@ -0,0 +1,62 @@ +# RFC Creation Process + +1. Copy the `rfc-template.md` file. Use the following filename pattern: `rfc-next_number-title.md` +2. Create a draft Pull Request if you want to get an early feedback. +3. Make sure the context and a solution is clear and well documented. +4. Add an entry to a list in the [README](README.md) file. +5. Create a Pull Request to propose a new ADR. + +## What is an RFC? + +An RFC is a sort of async whiteboarding session. It is meant to replace the need for a distributed team to come together to make a decision. Currently, the Cosmos SDK team and contributors are distributed around the world. The team conducts working groups to have a synchronous discussion and an RFC can be used to capture the discussion for a wider audience to better understand the changes that are coming to the software. + +The main difference the Cosmos SDK is defining as a differentiation between RFC and ADRs is that one is to come to consensus and circulate information about a potential change or feature. An ADR is used if there is already consensus on a feature or change and there is not a need to articulate the change coming to the software. An ADR will articulate the changes and have a lower amount of communication . + +## RFC life cycle + +RFC creation is an **iterative** process. An RFC is meant as a distributed colloboration session, it may have many comments and is usually the bi-product of no working group or synchornous communication + +1. Proposals could start with a new GitHub Issue, be a result of existing Issues or a discussion. + +2. An RFC doesn't have to arrive to `main` with an _accepted_ status in a single PR. If the motivation is clear and the solution is sound, we SHOULD be able to merge it and keep a _proposed_ status. It's preferable to have an iterative approach rather than long, not merged Pull Requests. + +3. If a _proposed_ RFC is merged, then it should clearly document outstanding issues either in the RFC document notes or in a GitHub Issue. + +4. The PR SHOULD always be merged. In the case of a faulty RFC, we still prefer to merge it with a _rejected_ status. The only time the RFC SHOULD NOT be merged is if the author abandons it. + +5. Merged RFCs SHOULD NOT be pruned. + +6. If there is consensus and enough feedback then the RFC can be accepted. + +> Note: An RFC is written when there is no working group or team session on the problem. RFC's are meant as a distributed white boarding session. If there is a working group on the proposal there is no need to have an RFC as there is synchornous whiteboarding going on. + +### RFC status + +Status has two components: + +```text +{CONSENSUS STATUS} +``` + +#### Consensus Status + +```text +DRAFT -> PROPOSED -> LAST CALL yyyy-mm-dd -> ACCEPTED | REJECTED -> SUPERSEDED by ADR-xxx + \ | + \ | + v v + ABANDONED +``` + +* `DRAFT`: [optional] an ADR which is work in progress, not being ready for a general review. This is to present an early work and get an early feedback in a Draft Pull Request form. +* `PROPOSED`: an ADR covering a full solution architecture and still in the review - project stakeholders haven't reached an agreed yet. +* `LAST CALL `: [optional] clear notify that we are close to accept updates. Changing a status to `LAST CALL` means that social consensus (of Cosmos SDK maintainers) has been reached and we still want to give it a time to let the community react or analyze. +* `ACCEPTED`: ADR which will represent a currently implemented or to be implemented architecture design. +* `REJECTED`: ADR can go from PROPOSED or ACCEPTED to rejected if the consensus among project stakeholders will decide so. +* `SUPERSEEDED by ADR-xxx`: ADR which has been superseded by a new ADR. +* `ABANDONED`: the ADR is no longer pursued by the original authors. + +## Language used in RFC + +* The background/goal should be written in the present tense. +* Avoid using a first, personal form. diff --git a/versioned_docs/version-0.47/integrate/rfc/README.md b/versioned_docs/version-0.47/integrate/rfc/README.md new file mode 100644 index 000000000..40559b626 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/rfc/README.md @@ -0,0 +1,34 @@ +--- +sidebar_position: 1 +--- + +# Requests for Comments + +A Request for Comments (RFC) is a record of discussion on an open-ended topic +related to the design and implementation of the Cosmos SDK, for which no +immediate decision is required. + +The purpose of an RFC is to serve as a historical record of a high-level +discussion that might otherwise only be recorded in an ad-hoc way (for example, +via gists or Google docs) that are difficult to discover for someone after the +fact. An RFC _may_ give rise to more specific architectural _decisions_ for +the Cosmos SDK, but those decisions must be recorded separately in +[Architecture Decision Records (ADR)](../architecture/README.md). + +As a rule of thumb, if you can articulate a specific question that needs to be +answered, write an ADR. If you need to explore the topic and get input from +others to know what questions need to be answered, an RFC may be appropriate. + +## RFC Content + +An RFC should provide: + +* A **changelog**, documenting when and how the RFC has changed. +* An **abstract**, briefly summarizing the topic so the reader can quickly tell + whether it is relevant to their interest. +* Any **background** a reader will need to understand and participate in the + substance of the discussion (links to other documents are fine here). +* The **discussion**, the primary content of the document. + +The [rfc-template.md](rfc-template.md) file includes placeholders for these +sections. diff --git a/versioned_docs/version-0.47/integrate/rfc/_category_.json b/versioned_docs/version-0.47/integrate/rfc/_category_.json new file mode 100644 index 000000000..40fac9822 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/rfc/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "RFCs", + "position": 12, + "link": null +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/rfc/rfc-001-tx-validation.md b/versioned_docs/version-0.47/integrate/rfc/rfc-001-tx-validation.md new file mode 100644 index 000000000..923e1c720 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/rfc/rfc-001-tx-validation.md @@ -0,0 +1,25 @@ +# RFC 001: Transaction Validation + +## Changelog + +* 2023-03-12: Proposed + +## Background + +Transation Validation is crucial to a functioning state machine. Within the Cosmos SDK there are two validation flows, one is outside the message server and the other within. The flow outside of the message server is the `ValidateBasic` function. It is called in the antehandler on both `CheckTx` and `DeliverTx`. There is an overhead and sometimes duplication of validation within these two flows. This extra validation provides an additional check before entering the mempool. + +With the deprecation of [`GetSigners`](https://github.com/cosmos/cosmos-sdk/issues/11275) we have the optionality to remove [sdk.Msg](https://github.com/cosmos/cosmos-sdk/blob/16a5404f8e00ddcf8857c8a55dca2f7c109c29bc/types/tx_msg.go#L16) and the `ValidateBasic` function. + +With the separation of CometBFT and Cosmos-SDK, there is a lack of control of what transactions get broadcasted and included in a block. This extra validation in the antehandler is meant to help in this case. In most cases the transaction is or should be simulated against a node for validation. With this flow transactions will be treated the same. + +## Proposal + +The acceptance of this RFC would move validation within `ValidateBasic` to the message server in modules, update tutorials and docs to remove mention of using `ValidateBasic` in favour of handling all validation for a message where it is executed. + +We can and will still support the `Validatebasic` function for users and provide an extension interface of the function once `sdk.Msg` is depreacted. + +> Note: This is how messages are handled in VMs like Ethereum and CosmWasm. + +### Consequences + +The consequence of updating the transaction flow is that transaction that may have failed before with the `ValidateBasic` flow will now be included in a block and fees charged. diff --git a/versioned_docs/version-0.47/integrate/rfc/rfc-template.md b/versioned_docs/version-0.47/integrate/rfc/rfc-template.md new file mode 100644 index 000000000..417a795d0 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/rfc/rfc-template.md @@ -0,0 +1,83 @@ +# RFC {RFC-NUMBER}: {TITLE} + +## Changelog + +* {date}: {changelog} + +## Background + +> The next section is the "Background" section. This section should be at least two paragraphs and can take up to a whole +> page in some cases. The guiding goal of the background section is: as a newcomer to this project (new employee, team +> transfer), can I read the background section and follow any links to get the full context of why this change is +> necessary? +> +> If you can't show a random engineer the background section and have them acquire nearly full context on the necessity +> for the RFC, then the background section is not full enough. To help achieve this, link to prior RFCs, discussions, and +> more here as necessary to provide context so you don't have to simply repeat yourself. + + +## Proposal + +> The next required section is "Proposal" or "Goal". Given the background above, this section proposes a solution. +> This should be an overview of the "how" for the solution, but for details further sections will be used. + + +## Abandoned Ideas (Optional) + +> As RFCs evolve, it is common that there are ideas that are abandoned. Rather than simply deleting them from the +> document, you should try to organize them into sections that make it clear they're abandoned while explaining why they +> were abandoned. +> +> When sharing your RFC with others or having someone look back on your RFC in the future, it is common to walk the same +> path and fall into the same pitfalls that we've since matured from. Abandoned ideas are a way to recognize that path +> and explain the pitfalls and why they were abandoned. + +## Descision + +> This section describes alternative designs to the chosen design. This section +> is important and if an adr does not have any alternatives then it should be +> considered that the ADR was not thought through. + +## Consequences (optional) + +> This section describes the resulting context, after applying the decision. All +> consequences should be listed here, not just the "positive" ones. A particular +> decision may have positive, negative, and neutral consequences, but all of them +> affect the team and project in the future. + +### Backwards Compatibility + +> All ADRs that introduce backwards incompatibilities must include a section +> describing these incompatibilities and their severity. The ADR must explain +> how the author proposes to deal with these incompatibilities. ADR submissions +> without a sufficient backwards compatibility treatise may be rejected outright. + +### Positive + +> {positive consequences} + +### Negative + +> {negative consequences} + +### Neutral + +> {neutral consequences} + + + +### References + +> Links to external materials needed to follow the discussion may be added here. +> +> In addition, if the discussion in a request for comments leads to any design +> decisions, it may be helpful to add links to the ADR documents here after the +> discussion has settled. + +## Discussion + +> This section contains the core of the discussion. +> +> There is no fixed format for this section, but ideally changes to this +> section should be updated before merging to reflect any discussion that took +> place on the PR that made those changes. diff --git a/versioned_docs/version-0.47/integrate/spec/README.md b/versioned_docs/version-0.47/integrate/spec/README.md deleted file mode 100644 index 3aec92297..000000000 --- a/versioned_docs/version-0.47/integrate/spec/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Specifications - -This directory contains specifications for the modules of the Cosmos SDK as well as Interchain Standards (ICS) and other specifications. - -Cosmos SDK applications hold this state in a Merkle store. Updates to -the store may be made during transactions and at the beginning and end of every -block. - -## Cosmos SDK specifications - -* [Store](./store) - The core Merkle store that holds the state. -* [Bech32](./addresses/bech32.md) - Address format for Cosmos SDK applications. - -## Modules specifications - -Go the [module directory](https://github.com/cosmos/cosmos-sdk/blob/main/x/README.md) - -## CometBFT - -For details on the underlying blockchain and p2p protocols, see -the [CometBFT specification](https://github.com/cometbft/cometbft/tree/main/spec). diff --git a/versioned_docs/version-0.47/integrate/spec/SPEC-SPEC.md b/versioned_docs/version-0.47/integrate/spec/SPEC_MODULE.md similarity index 98% rename from versioned_docs/version-0.47/integrate/spec/SPEC-SPEC.md rename to versioned_docs/version-0.47/integrate/spec/SPEC_MODULE.md index b9d90bc47..1b5e5d5dc 100644 --- a/versioned_docs/version-0.47/integrate/spec/SPEC-SPEC.md +++ b/versioned_docs/version-0.47/integrate/spec/SPEC_MODULE.md @@ -1,4 +1,4 @@ -# Specification of Specifications +# Specification of Modules This file intends to outline the common structure for specifications within this directory. diff --git a/versioned_docs/version-0.47/integrate/spec/SPEC_STANDARD.md b/versioned_docs/version-0.47/integrate/spec/SPEC_STANDARD.md new file mode 100644 index 000000000..3608b3654 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/spec/SPEC_STANDARD.md @@ -0,0 +1,121 @@ +# What is an SDK standard? + +An SDK standard is a design document describing a particular protocol, standard, or feature expected to be used by the Cosmos SDK. A SDK standard should list the desired properties of the standard, explain the design rationale, and provide a concise but comprehensive technical specification. The primary author is responsible for pushing the proposal through the standardization process, soliciting input and support from the community, and communicating with relevant stakeholders to ensure (social) consensus. + +## Sections + +A SDK standard consists of: + +* a synopsis, +* overview and basic concepts, +* technical specification, +* history log, and +* copyright notice. + +All top-level sections are required. References should be included inline as links, or tabulated at the bottom of the section if necessary. Included sub-sections should be listed in the order specified below. + +### Table Of Contents + +Provide a table of contents at the top of the file to assist readers. + +### Synopsis + +The document should include a brief (~200 word) synopsis providing a high-level description of and rationale for the specification. + +### Overview and basic concepts + +This section should include a motivation sub-section and a definitions sub-section if required: + +* *Motivation* - A rationale for the existence of the proposed feature, or the proposed changes to an existing feature. +* *Definitions* - A list of new terms or concepts utilized in the document or required to understand it. + +### System model and properties + +This section should include an assumptions sub-section if any, the mandatory properties sub-section, and a dependencies sub-section. Note that the first two sub-section are are tightly coupled: how to enforce a property will depend directly on the assumptions made. This sub-section is important to capture the interactions of the specified feature with the "rest-of-the-world", i.e., with other features of the ecosystem. + +* *Assumptions* - A list of any assumptions made by the feature designer. It should capture which features are used by the feature under specification, and what do we expect from them. +* *Properties* - A list of the desired properties or characteristics of the feature specified, and expected effects or failures when the properties are violated. In case it is relevant, it can also include a list of properties that the feature does not guarantee. +* *Dependencies* - A list of the features that use the feature under specification and how. + +### Technical specification + +This is the main section of the document, and should contain protocol documentation, design rationale, required references, and technical details where appropriate. +The section may have any or all of the following sub-sections, as appropriate to the particular specification. The API sub-section is especially encouraged when appropriate. + +* *API* - A detailed description of the features's API. +* *Technical Details* - All technical details including syntax, diagrams, semantics, protocols, data structures, algorithms, and pseudocode as appropriate. The technical specification should be detailed enough such that separate correct implementations of the specification without knowledge of each other are compatible. +* *Backwards Compatibility* - A discussion of compatibility (or lack thereof) with previous feature or protocol versions. +* *Known Issues* - A list of known issues. This sub-section is specially important for specifications of already in-use features. +* *Example Implementation* - A concrete example implementation or description of an expected implementation to serve as the primary reference for implementers. + +### History + +A specification should include a history section, listing any inspiring documents and a plaintext log of significant changes. + +See an example history section [below](#history-1). + +### Copyright + +A specification should include a copyright section waiving rights via [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). + +## Formatting + +### General + +Specifications must be written in GitHub-flavoured Markdown. + +For a GitHub-flavoured Markdown cheat sheet, see [here](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). For a local Markdown renderer, see [here](https://github.com/joeyespo/grip). + +### Language + +Specifications should be written in Simple English, avoiding obscure terminology and unnecessary jargon. For excellent examples of Simple English, please see the [Simple English Wikipedia](https://simple.wikipedia.org/wiki/Main_Page). + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in specifications are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +### Pseudocode + +Pseudocode in specifications should be language-agnostic and formatted in a simple imperative standard, with line numbers, variables, simple conditional blocks, for loops, and +English fragments where necessary to explain further functionality such as scheduling timeouts. LaTeX images should be avoided because they are difficult to review in diff form. + +Pseudocode for structs can be written in a simple language like Typescript or golang, as interfaces. + +Example Golang pseudocode struct: + +```go +type CacheKVStore interface { + cache: map[Key]Value + parent: KVStore + deleted: Key +} +``` + +Pseudocode for algorithms should be written in simple Golang, as functions. + +Example pseudocode algorithm: + +```go +func get( + store CacheKVStore, + key Key) Value { + + value = store.cache.get(Key) + if (value !== null) { + return value + } else { + value = store.parent.get(key) + store.cache.set(key, value) + return value + } +} +``` + +## History + +This specification was significantly inspired by and derived from IBC's [ICS](https://github.com/cosmos/ibc/blob/main/spec/ics-001-ics-standard/README.md), which +was in turn derived from Ethereum's [EIP 1](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md). + +Nov 24, 2022 - Initial draft finished and submitted as a PR + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/versioned_docs/version-0.47/integrate/spec/_category_.json b/versioned_docs/version-0.47/integrate/spec/_category_.json index e77f62999..0f1092344 100644 --- a/versioned_docs/version-0.47/integrate/spec/_category_.json +++ b/versioned_docs/version-0.47/integrate/spec/_category_.json @@ -1,5 +1,5 @@ { "label": "Specifications", - "position": 11, + "position": 6, "link": null -} +} \ No newline at end of file diff --git a/versioned_docs/version-0.47/integrate/spec/_ics/README.md b/versioned_docs/version-0.47/integrate/spec/_ics/README.md deleted file mode 100644 index 803e0c89c..000000000 --- a/versioned_docs/version-0.47/integrate/spec/_ics/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Cosmos ICS - -* [ICS030 - Signed Messages](./ics-030-signed-messages.md) diff --git a/versioned_docs/version-0.47/integrate/spec/addresses/README.md b/versioned_docs/version-0.47/integrate/spec/addresses/README.md index 61db3aa93..af63429d5 100644 --- a/versioned_docs/version-0.47/integrate/spec/addresses/README.md +++ b/versioned_docs/version-0.47/integrate/spec/addresses/README.md @@ -1,3 +1,3 @@ # Addresses spec -* [Bech32](./bech32.md) +* [Bech32](bech32.md) diff --git a/versioned_docs/version-0.47/integrate/spec/addresses/bech32.md b/versioned_docs/version-0.47/integrate/spec/addresses/bech32.md index 2c15bac68..f996f9016 100644 --- a/versioned_docs/version-0.47/integrate/spec/addresses/bech32.md +++ b/versioned_docs/version-0.47/integrate/spec/addresses/bech32.md @@ -18,4 +18,4 @@ While all user facing interfaces to Cosmos software should exposed Bech32 interf To covert between other binary representation of addresses and keys, it is important to first apply the Amino encoding process before Bech32 encoding. -A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/cometbft/cometbft/blob/main/spec/blockchain/encoding.md) to the byte string payload before Bech32 encoding will sufficient for compatible representation. +A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/cometbft/cometbft/blob/main/spec/blockchain/05-encoding.md) to the byte string payload before Bech32 encoding will sufficient for compatible representation. diff --git a/versioned_docs/version-0.47/integrate/spec/circuit-breaker/README.md b/versioned_docs/version-0.47/integrate/spec/circuit-breaker/README.md deleted file mode 100644 index 1956704bd..000000000 --- a/versioned_docs/version-0.47/integrate/spec/circuit-breaker/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Concepts - -The intention of the circuit breaker is to have a contingency plan for a -running network which maintains network liveness. This can be achieved through -selectively "pausing" functionality of specific modules on a running network. -The circuit breaker is intended to be enabled through either: - -* governance -* for emergencies a special subset of accounts selected by the state machine -* a transaction which proves the expected behaviour is broken - -## Pause state - -The basic pause state of any module simply disables all message routes to -that module. Beyond that, it may be a appropriate for different modules to -process begin-block/end-block in an altered "safe" way. diff --git a/versioned_docs/version-0.47/integrate/spec/ics/README.md b/versioned_docs/version-0.47/integrate/spec/ics/README.md new file mode 100644 index 000000000..ce0cf31a8 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/spec/ics/README.md @@ -0,0 +1,3 @@ +# Cosmos ICS + +* [ICS030 - Signed Messages](ics-030-signed-messages.md) diff --git a/versioned_docs/version-0.47/integrate/spec/_ics/ics-030-signed-messages.md b/versioned_docs/version-0.47/integrate/spec/ics/ics-030-signed-messages.md similarity index 99% rename from versioned_docs/version-0.47/integrate/spec/_ics/ics-030-signed-messages.md rename to versioned_docs/version-0.47/integrate/spec/ics/ics-030-signed-messages.md index 991314905..a7c56715b 100644 --- a/versioned_docs/version-0.47/integrate/spec/_ics/ics-030-signed-messages.md +++ b/versioned_docs/version-0.47/integrate/spec/ics/ics-030-signed-messages.md @@ -89,7 +89,7 @@ must equal the constant `"message"`. The `@type` field corresponds to the type o structure the user will be signing in an application. For now, a user is only allowed to sign bytes of valid ASCII text ([see here](https://github.com/cometbft/cometbft/blob/v0.37.0/libs/strings/string.go#L35-L64)). However, this will change and evolve to support additional application-specific -structures that are human-readable and machine-verifiable ([see Future Adaptations](#futureadaptations)). +structures that are human-readable and machine-verifiable ([see Future Adaptations](#future-adaptations)). Thus, we can have a canonical JSON structure for signing Cosmos messages using the [JSON schema](http://json-schema.org/) specification as such: diff --git a/versioned_docs/version-0.47/integrate/spec/reserve-pool/README.md b/versioned_docs/version-0.47/integrate/spec/reserve-pool/README.md deleted file mode 100644 index 6912ab0c4..000000000 --- a/versioned_docs/version-0.47/integrate/spec/reserve-pool/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Reserve Pool - -The reserve pool is the pool of collected funds for use by governance taken via the `CommunityTax`. -Currently with the Cosmos SDK, tokens collected by the CommunityTax are accounted for but unspendable. diff --git a/versioned_docs/version-0.47/integrate/spec/store/README.md b/versioned_docs/version-0.47/integrate/spec/store/README.md deleted file mode 100644 index c53d69c67..000000000 --- a/versioned_docs/version-0.47/integrate/spec/store/README.md +++ /dev/null @@ -1,235 +0,0 @@ -# Store - -The store package defines the interfaces, types and abstractions for Cosmos SDK -modules to read and write to Merkleized state within a Cosmos SDK application. -The store package provides many primitives for developers to use in order to -work with both state storage and state commitment. Below we describe the various -abstractions. - -## Types - -### `Store` - -The bulk of the store interfaces are defined [here](https://github.com/cosmos/cosmos-sdk/blob/main/store/types/store.go), -where the base primitive interface, for which other interfaces build off of, is -the `Store` type. The `Store` interface defines the ability to tell the type of -the implementing store and the ability to cache wrap via the `CacheWrapper` interface. - -### `CacheWrapper` & `CacheWrap` - -One of the most important features a store has the ability to perform is the -ability to cache wrap. Cache wrapping is essentially the underlying store wrapping -itself within another store type that performs caching for both reads and writes -with the ability to flush writes via `Write()`. - -### `KVStore` & `CacheKVStore` - -One of the most important interfaces that both developers and modules interface -with, which also provides the basis of most state storage and commitment operations, -is the `KVStore`. The `KVStore` interface provides basic CRUD abilities and -prefix-based iteration, including reverse iteration. - -Typically, each module has it's own dedicated `KVStore` instance, which it can -get access to via the `sdk.Context` and the use of a pointer-based named key -- -`KVStoreKey`. The `KVStoreKey` provides pseudo-OCAP. How a exactly a `KVStoreKey` -maps to a `KVStore` will be illustrated below through the `CommitMultiStore`. - -Note, a `KVStore` cannot directly commit state. Instead, a `KVStore` can be wrapped -by a `CacheKVStore` which extends a `KVStore` and provides the ability for the -caller to execute `Write()` which commits state to the underlying state storage. -Note, this doesn't actually flush writes to disk as writes are held in memory -until `Commit()` is called on the `CommitMultiStore`. - -### `CommitMultiStore` - -The `CommitMultiStore` interface exposes the the top-level interface that is used -to manage state commitment and storage by an SDK application and abstracts the -concept of multiple `KVStore`s which are used by multiple modules. Specifically, -it supports the following high-level primitives: - -* Allows for a caller to retrieve a `KVStore` by providing a `KVStoreKey`. -* Exposes pruning mechanisms to remove state pinned against a specific height/version - in the past. -* Allows for loading state storage at a particular height/version in the past to - provide current head and historical queries. -* Provides the ability to rollback state to a previous height/version. -* Provides the ability to to load state storage at a particular height/version - while also performing store upgrades, which are used during live hard-fork - application state migrations. -* Provides the ability to commit all current accumulated state to disk and performs - Merkle commitment. - -## Implementation Details - -While there are many interfaces that the `store` package provides, there is -typically a core implementation for each main interface that modules and -developers interact with that are defined in the Cosmos SDK. - -### `iavl.Store` - -The `iavl.Store` provides the core implementation for state storage and commitment -by implementing the following interfaces: - -* `KVStore` -* `CommitStore` -* `CommitKVStore` -* `Queryable` -* `StoreWithInitialVersion` - -It allows for all CRUD operations to be performed along with allowing current -and historical state queries, prefix iteration, and state commitment along with -Merkle proof operations. The `iavl.Store` also provides the ability to remove -historical state from the state commitment layer. - -An overview of the IAVL implementation can be found [here](https://github.com/cosmos/iavl/blob/master/docs/overview.md). -It is important to note that the IAVL store provides both state commitment and -logical storage operations, which comes with drawbacks as there are various -performance impacts, some of which are very drastic, when it comes to the -operations mentioned above. - -When dealing with state management in modules and clients, the Cosmos SDK provides -various layers of abstractions or "store wrapping", where the `iavl.Store` is the -bottom most layer. When requesting a store to perform reads or writes in a module, -the typical abstraction layer in order is defined as follows: - -```text -iavl.Store <- cachekv.Store <- gaskv.Store <- cachemulti.Store <- rootmulti.Store -``` - -### Concurrent use of IAVL store - -The tree under `iavl.Store` is not safe for concurrent use. It is the -responsibility of the caller to ensure that concurrent access to the store is -not performed. - -The main issue with concurrent use is when data is written at the same time as -it's being iterated over. Doing so will cause a irrecoverable fatal error because -of concurrent reads and writes to an internal map. - -Although it's not recommended, you can iterate through values while writing to -it by disabling "FastNode" **without guarantees that the values being written will -be returned during the iteration** (if you need this, you might want to reconsider -the design of your application). This is done by setting `iavl-disable-fastnode` -to `true` in the config TOML file. - -### `cachekv.Store` - -The `cachekv.Store` store wraps an underlying `KVStore`, typically a `iavl.Store` -and contains an in-memory cache for storing pending writes to underlying `KVStore`. -`Set` and `Delete` calls are executed on the in-memory cache, whereas `Has` calls -are proxied to the underlying `KVStore`. - -One of the most important calls to a `cachekv.Store` is `Write()`, which ensures -that key-value pairs are written to the underlying `KVStore` in a deterministic -and ordered manner by sorting the keys first. The store keeps track of "dirty" -keys and uses these to determine what keys to sort. In addition, it also keeps -track of deleted keys and ensures these are also removed from the underlying -`KVStore`. - -The `cachekv.Store` also provides the ability to perform iteration and reverse -iteration. Iteration is performed through the `cacheMergeIterator` type and uses -both the dirty cache and underlying `KVStore` to iterate over key-value pairs. - -Note, all calls to CRUD and iteration operations on a `cachekv.Store` are thread-safe. - -### `gaskv.Store` - -The `gaskv.Store` store provides a simple implementation of a `KVStore`. -Specifically, it just wraps an existing `KVStore`, such as a cache-wrapped -`iavl.Store`, and incurs configurable gas costs for CRUD operations via -`ConsumeGas()` calls defined on the `GasMeter` which exists in a `sdk.Context` -and then proxies the underlying CRUD call to the underlying store. Note, the -`GasMeter` is reset on each block. - -### `cachemulti.Store` & `rootmulti.Store` - -The `rootmulti.Store` acts as an abstraction around a series of stores. Namely, -it implements the `CommitMultiStore` an `Queryable` interfaces. Through the -`rootmulti.Store`, an SDK module can request access to a `KVStore` to perform -state CRUD operations and queries by holding access to a unique `KVStoreKey`. - -The `rootmulti.Store` ensures these queries and state operations are performed -through cached-wrapped instances of `cachekv.Store` which is described above. The -`rootmulti.Store` implementation is also responsible for committing all accumulated -state from each `KVStore` to disk and returning an application state Merkle root. - -Queries can be performed to return state data along with associated state -commitment proofs for both previous heights/versions and the current state root. -Queries are routed based on store name, i.e. a module, along with other parameters -which are defined in `abci.RequestQuery`. - -The `rootmulti.Store` also provides primitives for pruning data at a given -height/version from state storage. When a height is committed, the `rootmulti.Store` -will determine if other previous heights should be considered for removal based -on the operator's pruning settings defined by `PruningOptions`, which defines -how many recent versions to keep on disk and the interval at which to remove -"staged" pruned heights from disk. During each interval, the staged heights are -removed from each `KVStore`. Note, it is up to the underlying `KVStore` -implementation to determine how pruning is actually performed. The `PruningOptions` -are defined as follows: - -```go -type PruningOptions struct { - // KeepRecent defines how many recent heights to keep on disk. - KeepRecent uint64 - - // Interval defines when the pruned heights are removed from disk. - Interval uint64 - - // Strategy defines the kind of pruning strategy. See below for more information on each. - Strategy PruningStrategy -} -``` - -The Cosmos SDK defines a preset number of pruning "strategies": `default`, `everything` -`nothing`, and `custom`. - -It is important to note that the `rootmulti.Store` considers each `KVStore` as a -separate logical store. In other words, they do not share a Merkle tree or -comparable data structure. This means that when state is committed via -`rootmulti.Store`, each store is committed in sequence and thus is not atomic. - -In terms of store construction and wiring, each Cosmos SDK application contains -a `BaseApp` instance which internally has a reference to a `CommitMultiStore` -that is implemented by a `rootmulti.Store`. The application then registers one or -more `KVStoreKey` that pertain to a unique module and thus a `KVStore`. Through -the use of an `sdk.Context` and a `KVStoreKey`, each module can get direct access -to it's respective `KVStore` instance. - -Example: - -```go -func NewApp(...) Application { - // ... - - bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...) - bApp.SetCommitMultiStoreTracer(traceStore) - bApp.SetVersion(version.Version) - bApp.SetInterfaceRegistry(interfaceRegistry) - - // ... - - keys := sdk.NewKVStoreKeys(...) - transientKeys := sdk.NewTransientStoreKeys(...) - memKeys := sdk.NewMemoryStoreKeys(...) - - // ... - - // initialize stores - app.MountKVStores(keys) - app.MountTransientStores(transientKeys) - app.MountMemoryStores(memKeys) - - // ... -} -``` - -The `rootmulti.Store` itself can be cache-wrapped which returns an instance of a -`cachemulti.Store`. For each block, `BaseApp` ensures that the proper abstractions -are created on the `CommitMultiStore`, i.e. ensuring that the `rootmulti.Store` -is cached-wrapped and uses the resulting `cachemulti.Store` to be set on the -`sdk.Context` which is then used for block and transaction execution. As a result, -all state mutations due to block and transaction execution are actually held -ephemerally until `Commit()` is called by the ABCI client. This concept is further -expanded upon when the AnteHandler is executed per transaction to ensure state -is not committed for transactions that failed CheckTx. diff --git a/versioned_docs/version-0.47/integrate/tooling/00-protobuf.md b/versioned_docs/version-0.47/integrate/tooling/00-protobuf.md index 42e9d3bf0..ee1f444fe 100644 --- a/versioned_docs/version-0.47/integrate/tooling/00-protobuf.md +++ b/versioned_docs/version-0.47/integrate/tooling/00-protobuf.md @@ -6,7 +6,7 @@ sidebar_position: 1 It is known that Cosmos SDK uses protocol buffers extensively, this docuemnt is meant to provide a guide on how it is used in the cosmos-sdk. -To generate the proto file, the Cosmos SDK uses a docker image, this image is provided to all to use as well. The latest version is `ghcr.io/cosmos/proto-builder:0.11.2` +To generate the proto file, the Cosmos SDK uses a docker image, this image is provided to all to use as well. The latest version is `ghcr.io/cosmos/proto-builder:0.12.x` Below is the example of the Cosmos SDK's commands for generating, linting, and formatting protobuf files that can be reused in any applications makefile. @@ -39,7 +39,7 @@ https://github.com/cosmos/cosmos-sdk/blob/main/buf.work.yaml#L6-L9 Next is the `proto/` directory where all of our protobuf files live. In here there are many different buf files defined each serving a different purpose. ```bash -├── README.md +├── 05-depinject.md ├── buf.gen.gogo.yaml ├── buf.gen.pulsar.yaml ├── buf.gen.swagger.yaml diff --git a/versioned_docs/version-0.47/integrate/tooling/01-cosmovisor.md b/versioned_docs/version-0.47/integrate/tooling/01-cosmovisor.md new file mode 100644 index 000000000..08e01f5a9 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/tooling/01-cosmovisor.md @@ -0,0 +1,366 @@ +--- +sidebar_position: 1 +--- + +# Cosmovisor + +`cosmovisor` is a small process manager for Cosmos SDK application binaries that monitors the governance module for incoming chain upgrade proposals. If it sees a proposal that gets approved, `cosmovisor` can automatically download the new binary, stop the current binary, switch from the old binary to the new one, and finally restart the node with the new binary. + +* [Design](#design) +* [Contributing](#contributing) +* [Setup](#setup) + * [Installation](#installation) + * [Command Line Arguments And Environment Variables](#command-line-arguments-and-environment-variables) + * [Folder Layout](#folder-layout) +* [Usage](#usage) + * [Initialization](#initialization) + * [Detecting Upgrades](#detecting-upgrades) + * [Auto-Download](#auto-download) +* [Example: SimApp Upgrade](#example-simapp-upgrade) + * [Chain Setup](#chain-setup) + * [Prepare Cosmovisor and Start the Chain](#prepare-cosmovisor-and-start-the-chain) + * [Update App](#update-app) + +## Design + +Cosmovisor is designed to be used as a wrapper for a `Cosmos SDK` app: + +* it will pass arguments to the associated app (configured by `DAEMON_NAME` env variable). + Running `cosmovisor run arg1 arg2 ....` will run `app arg1 arg2 ...`; +* it will manage an app by restarting and upgrading if needed; +* it is configured using environment variables, not positional arguments. + +*Note: If new versions of the application are not set up to run in-place store migrations, migrations will need to be run manually before restarting `cosmovisor` with the new binary. For this reason, we recommend applications adopt in-place store migrations.* + +*Note: If validators would like to enable the auto-download option (which [we don't recommend](#auto-download)), and they are currently running an application using Cosmos SDK `v0.42`, they will need to use Cosmovisor [`v0.1`](https://github.com/cosmos/cosmos-sdk/releases/tag/cosmovisor%2Fv0.1.0). Later versions of Cosmovisor do not support Cosmos SDK `v0.44.3` or earlier if the auto-download option is enabled.* + +## Contributing + +Cosmovisor is part of the Cosmos SDK monorepo, but it's a separate module with it's own release schedule. + +Release branches have the following format `release/cosmovisor/vA.B.x`, where A and B are a number (e.g. `release/cosmovisor/v1.3.x`). Releases are tagged using the following format: `cosmovisor/vA.B.C`. + +## Setup + +### Installation + +You can download Cosmovisor from the [GitHub releases](https://github.com/cosmos/cosmos-sdk/releases/tag/cosmovisor%2Fv1.3.0). + +To install the latest version of `cosmovisor`, run the following command: + +```shell +go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@latest +``` + +To install a previous version, you can specify the version. IMPORTANT: Chains that use Cosmos SDK v0.44.3 or earlier (eg v0.44.2) and want to use auto-download feature MUST use `cosmovisor v0.1.0` + +```shell +go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v0.1.0 +``` + +Run `cosmovisor version` to check the cosmovisor version. + +Alternatively, for building from source, simply run `make cosmovisor`. The binary will be located in `tools/cosmovisor`. + +:::warning +Building from source using `make cosmovisor` won't display the correct `cosmovisor` version. +::: + +### Command Line Arguments And Environment Variables + +The first argument passed to `cosmovisor` is the action for `cosmovisor` to take. Options are: + +* `help`, `--help`, or `-h` - Output `cosmovisor` help information and check your `cosmovisor` configuration. +* `run` - Run the configured binary using the rest of the provided arguments. +* `version` - Output the `cosmovisor` version and also run the binary with the `version` argument. + +All arguments passed to `cosmovisor run` will be passed to the application binary (as a subprocess). `cosmovisor` will return `/dev/stdout` and `/dev/stderr` of the subprocess as its own. For this reason, `cosmovisor run` cannot accept any command-line arguments other than those available to the application binary. + +*Note: Use of `cosmovisor` without one of the action arguments is deprecated. For backwards compatibility, if the first argument is not an action argument, `run` is assumed. However, this fallback might be removed in future versions, so it is recommended that you always provide `run`. + +`cosmovisor` reads its configuration from environment variables: + +* `DAEMON_HOME` is the location where the `cosmovisor/` directory is kept that contains the genesis binary, the upgrade binaries, and any additional auxiliary files associated with each binary (e.g. `$HOME/.gaiad`, `$HOME/.regend`, `$HOME/.simd`, etc.). +* `DAEMON_NAME` is the name of the binary itself (e.g. `gaiad`, `regend`, `simd`, etc.). +* `DAEMON_ALLOW_DOWNLOAD_BINARIES` (*optional*), if set to `true`, will enable auto-downloading of new binaries (for security reasons, this is intended for full nodes rather than validators). By default, `cosmovisor` will not auto-download new binaries. +* `DAEMON_RESTART_AFTER_UPGRADE` (*optional*, default = `true`), if `true`, restarts the subprocess with the same command-line arguments and flags (but with the new binary) after a successful upgrade. Otherwise (`false`), `cosmovisor` stops running after an upgrade and requires the system administrator to manually restart it. Note restart is only after the upgrade and does not auto-restart the subprocess after an error occurs. +* `DAEMON_RESTART_DELAY` (*optional*, default none), allow a node operator to define a delay between the node halt (for upgrade) and backup by the specified time. The value must be a duration (e.g. `1s`). +* `DAEMON_POLL_INTERVAL` (*optional*, default 300 milliseconds), is the interval length for polling the upgrade plan file. The value must be a duration (e.g. `1s`). +* `DAEMON_DATA_BACKUP_DIR` option to set a custom backup directory. If not set, `DAEMON_HOME` is used. +* `UNSAFE_SKIP_BACKUP` (defaults to `false`), if set to `true`, upgrades directly without performing a backup. Otherwise (`false`, default) backs up the data before trying the upgrade. The default value of false is useful and recommended in case of failures and when a backup needed to rollback. We recommend using the default backup option `UNSAFE_SKIP_BACKUP=false`. +* `DAEMON_PREUPGRADE_MAX_RETRIES` (defaults to `0`). The maximum number of times to call `pre-upgrade` in the application after exit status of `31`. After the maximum number of retries, Cosmovisor fails the upgrade. +* `COSMOVISOR_DISABLE_LOGS` (defaults to `false`). If set to true, this will disable Cosmovisor logs (but not the underlying process) completely. This may be useful, for example, when a Cosmovisor subcommand you are executing returns a valid JSON you are then parsing, as logs added by Cosmovisor make this output not a valid JSON. + +### Folder Layout + +`$DAEMON_HOME/cosmovisor` is expected to belong completely to `cosmovisor` and the subprocesses that are controlled by it. The folder content is organized as follows: + +```text +. +├── current -> genesis or upgrades/ +├── genesis +│   └── bin +│   └── $DAEMON_NAME +└── upgrades + └── + ├── bin + │   └── $DAEMON_NAME + └── upgrade-info.json +``` + +The `cosmovisor/` directory incudes a subdirectory for each version of the application (i.e. `genesis` or `upgrades/`). Within each subdirectory is the application binary (i.e. `bin/$DAEMON_NAME`) and any additional auxiliary files associated with each binary. `current` is a symbolic link to the currently active directory (i.e. `genesis` or `upgrades/`). The `name` variable in `upgrades/` is the lowercased URI-encoded name of the upgrade as specified in the upgrade module plan. Note that the upgrade name path are normalized to be lowercased: for instance, `MyUpgrade` is normalized to `myupgrade`, and its path is `upgrades/myupgrade`. + +Please note that `$DAEMON_HOME/cosmovisor` only stores the *application binaries*. The `cosmovisor` binary itself can be stored in any typical location (e.g. `/usr/local/bin`). The application will continue to store its data in the default data directory (e.g. `$HOME/.gaiad`) or the data directory specified with the `--home` flag. `$DAEMON_HOME` is independent of the data directory and can be set to any location. If you set `$DAEMON_HOME` to the same directory as the data directory, you will end up with a configuation like the following: + +```text +.gaiad +├── config +├── data +└── cosmovisor +``` + +## Usage + +The system administrator is responsible for: + +* installing the `cosmovisor` binary +* configuring the host's init system (e.g. `systemd`, `launchd`, etc.) +* appropriately setting the environmental variables +* creating the `/cosmovisor` directory +* creating the `/cosmovisor/genesis/bin` folder +* creating the `/cosmovisor/upgrades//bin` folders +* placing the different versions of the `` executable in the appropriate `bin` folders. + +`cosmovisor` will set the `current` link to point to `genesis` at first start (i.e. when no `current` link exists) and then handle switching binaries at the correct points in time so that the system administrator can prepare days in advance and relax at upgrade time. + +In order to support downloadable binaries, a tarball for each upgrade binary will need to be packaged up and made available through a canonical URL. Additionally, a tarball that includes the genesis binary and all available upgrade binaries can be packaged up and made available so that all the necessary binaries required to sync a fullnode from start can be easily downloaded. + +The `DAEMON` specific code and operations (e.g. cometBFT config, the application db, syncing blocks, etc.) all work as expected. The application binaries' directives such as command-line flags and environment variables also work as expected. + +### Initialization + +The `cosmovisor init ` command creates the folder structure required for using cosmovisor. + +It does the following: + +* creates the `/cosmovisor` folder if it doesn't yet exist +* creates the `/cosmovisor/genesis/bin` folder if it doesn't yet exist +* copies the provided executable file to `/cosmovisor/genesis/bin/` +* creates the `current` link, pointing to the `genesis` folder + +It uses the `DAEMON_HOME` and `DAEMON_NAME` environment variables for folder location and executable name. + +The `cosmovisor init` command is specifically for initializing cosmovisor, and should not be confused with a chain's `init` command (e.g. `cosmovisor run init`). + +### Detecting Upgrades + +`cosmovisor` is polling the `$DAEMON_HOME/data/upgrade-info.json` file for new upgrade instructions. The file is created by the x/upgrade module in `BeginBlocker` when an upgrade is detected and the blockchain reaches the upgrade height. +The following heuristic is applied to detect the upgrade: + +* When starting, `cosmovisor` doesn't know much about currently running upgrade, except the binary which is `current/bin/`. It tries to read the `current/update-info.json` file to get information about the current upgrade name. +* If neither `cosmovisor/current/upgrade-info.json` nor `data/upgrade-info.json` exist, then `cosmovisor` will wait for `data/upgrade-info.json` file to trigger an upgrade. +* If `cosmovisor/current/upgrade-info.json` doesn't exist but `data/upgrade-info.json` exists, then `cosmovisor` assumes that whatever is in `data/upgrade-info.json` is a valid upgrade request. In this case `cosmovisor` tries immediately to make an upgrade according to the `name` attribute in `data/upgrade-info.json`. +* Otherwise, `cosmovisor` waits for changes in `upgrade-info.json`. As soon as a new upgrade name is recorded in the file, `cosmovisor` will trigger an upgrade mechanism. + +When the upgrade mechanism is triggered, `cosmovisor` will: + +1. if `DAEMON_ALLOW_DOWNLOAD_BINARIES` is enabled, start by auto-downloading a new binary into `cosmovisor//bin` (where `` is the `upgrade-info.json:name` attribute); +2. update the `current` symbolic link to point to the new directory and save `data/upgrade-info.json` to `cosmovisor/current/upgrade-info.json`. + +### Auto-Download + +Generally, `cosmovisor` requires that the system administrator place all relevant binaries on disk before the upgrade happens. However, for people who don't need such control and want an automated setup (maybe they are syncing a non-validating fullnode and want to do little maintenance), there is another option. + +**NOTE: we don't recommend using auto-download** because it doesn't verify in advance if a binary is available. If there will be any issue with downloading a binary, the cosmovisor will stop and won't restart an App (which could lead to a chain halt). + +If `DAEMON_ALLOW_DOWNLOAD_BINARIES` is set to `true`, and no local binary can be found when an upgrade is triggered, `cosmovisor` will attempt to download and install the binary itself based on the instructions in the `info` attribute in the `data/upgrade-info.json` file. The files is constructed by the x/upgrade module and contains data from the upgrade `Plan` object. The `Plan` has an info field that is expected to have one of the following two valid formats to specify a download: + +1. Store an os/architecture -> binary URI map in the upgrade plan info field as JSON under the `"binaries"` key. For example: + + ```json + { + "binaries": { + "linux/amd64":"https://example.com/gaia.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" + } + } + ``` + + You can include multiple binaries at once to ensure more than one environment will receive the correct binaries: + + ```json + { + "binaries": { + "linux/amd64":"https://example.com/gaia.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", + "linux/arm64":"https://example.com/gaia.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", + "darwin/amd64":"https://example.com/gaia.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" + } + } + ``` + + When submitting this as a proposal ensure there are no spaces. An example command using `gaiad` could look like: + + ```shell + > gaiad tx upgrade software-upgrade Vega \ + --title Vega \ + --deposit 100uatom \ + --upgrade-height 7368420 \ + --upgrade-info '{"binaries":{"linux/amd64":"https://github.com/cosmos/gaia/releases/download/v6.0.0-rc1/gaiad-v6.0.0-rc1-linux-amd64","linux/arm64":"https://github.com/cosmos/gaia/releases/download/v6.0.0-rc1/gaiad-v6.0.0-rc1-linux-arm64","darwin/amd64":"https://github.com/cosmos/gaia/releases/download/v6.0.0-rc1/gaiad-v6.0.0-rc1-darwin-amd64"}}' \ + --summary "upgrade to Vega" \ + --gas 400000 \ + --from user \ + --chain-id test \ + --home test/val2 \ + --node tcp://localhost:36657 \ + --yes + ``` + +2. Store a link to a file that contains all information in the above format (e.g. if you want to specify lots of binaries, changelog info, etc. without filling up the blockchain). For example: + + ```text + https://example.com/testnet-1001-info.json?checksum=sha256:deaaa99fda9407c4dbe1d04bd49bab0cc3c1dd76fa392cd55a9425be074af01e + ``` + +When `cosmovisor` is triggered to download the new binary, `cosmovisor` will parse the `"binaries"` field, download the new binary with [go-getter](https://github.com/hashicorp/go-getter), and unpack the new binary in the `upgrades/` folder so that it can be run as if it was installed manually. + +Note that for this mechanism to provide strong security guarantees, all URLs should include a SHA 256/512 checksum. This ensures that no false binary is run, even if someone hacks the server or hijacks the DNS. `go-getter` will always ensure the downloaded file matches the checksum if it is provided. `go-getter` will also handle unpacking archives into directories (in this case the download link should point to a `zip` file of all data in the `bin` directory). + +To properly create a sha256 checksum on linux, you can use the `sha256sum` utility. For example: + +```shell +sha256sum ./testdata/repo/zip_directory/autod.zip +``` + +The result will look something like the following: `29139e1381b8177aec909fab9a75d11381cab5adf7d3af0c05ff1c9c117743a7`. + +You can also use `sha512sum` if you would prefer to use longer hashes, or `md5sum` if you would prefer to use broken hashes. Whichever you choose, make sure to set the hash algorithm properly in the checksum argument to the URL. + +## Example: SimApp Upgrade + +The following instructions provide a demonstration of `cosmovisor` using the simulation application (`simapp`) shipped with the Cosmos SDK's source code. The following commands are to be run from within the `cosmos-sdk` repository. + +### Chain Setup + +Let's create a new chain using the `v0.44` version of simapp (the Cosmos SDK demo app): + +```shell +git checkout v0.44.6 +make build +``` + +Clean `~/.simapp` (never do this in a production environment): + +```shell +./build/simd unsafe-reset-all +``` + +Set up app config: + +```shell +./build/simd config set client chain-id test +./build/simd config set client keyring-backend test +./build/simd config set client broadcast-mode sync +``` + +Initialize the node and overwrite any previous genesis file (never do this in a production environment): + + + +```shell +./build/simd init test --chain-id test --overwrite +``` + +Set the minimum gas price to `0stake` in `~/.simapp/config/app.toml`: + +```shell +minimum-gas-prices = "0stake" +``` + +For the sake of this demonstration, amend `voting_period` in `genesis.json` to a reduced time of 20 seconds (`20s`): + +```shell +cat <<< $(jq '.app_state.gov.voting_params.voting_period = "20s"' $HOME/.simapp/config/genesis.json) > $HOME/.simapp/config/genesis.json +``` + +Create a validator, and setup genesis transaction: + +```shell +./build/simd keys add validator +./build/simd genesis add-genesis-account validator 1000000000stake --keyring-backend test +./build/simd genesis gentx validator 1000000stake --chain-id test +./build/simd genesis collect-gentxs +``` + +#### Prepare Cosmovisor and Start the Chain + +Set the required environment variables: + +```shell +export DAEMON_NAME=simd +export DAEMON_HOME=$HOME/.simapp +``` + +Set the optional environment variable to trigger an automatic app restart: + +```shell +export DAEMON_RESTART_AFTER_UPGRADE=true +``` + +Create the folder for the genesis binary and copy the `simd` binary: + +```shell +mkdir -p $DAEMON_HOME/cosmovisor/genesis/bin +cp ./build/simd $DAEMON_HOME/cosmovisor/genesis/bin +``` + +Now you can run cosmovisor with simapp v0.44: + +```shell +cosmovisor run start +``` + +#### Update App + +Update app to the latest version (e.g. v0.45). + +Next, we can add a migration - which is defined using `x/upgrade` [upgrade plan](https://github.com/cosmos/cosmos-sdk/blob/main/docs/advanced-concepts/13-upgrade.md) (you may refer to a past version if you are using an older Cosmos SDK release). In a migration we can do any deterministic state change. + +Build the new version `simd` binary: + +```shell +make build +``` + +Create the folder for the upgrade binary and copy the `simd` binary: + +```shell +mkdir -p $DAEMON_HOME/cosmovisor/upgrades/test1/bin +cp ./build/simd $DAEMON_HOME/cosmovisor/upgrades/test1/bin +``` + +Open a new terminal window and submit an upgrade proposal along with a deposit and a vote (these commands must be run within 20 seconds of each other): + +**<= v0.45**: + +```shell +./build/simd tx gov submit-proposal software-upgrade test1 --title upgrade --description upgrade --upgrade-height 200 --from validator --yes +./build/simd tx gov deposit 1 10000000stake --from validator --yes +./build/simd tx gov vote 1 yes --from validator --yes +``` + +**v0.46, v0.47**: + +```shell +./build/simd tx gov submit-legacy-proposal software-upgrade test1 --title upgrade --description upgrade --upgrade-height 200 --from validator --yes +./build/simd tx gov deposit 1 10000000stake --from validator --yes +./build/simd tx gov vote 1 yes --from validator --yes +``` + +**>= v0.48+**: + +```shell +./build/simd tx upgrade software-upgrade test1 --title upgrade --summary upgrade --upgrade-height 200 --from validator --yes +./build/simd tx gov deposit 1 10000000stake --from validator --yes +./build/simd tx gov vote 1 yes --from validator --yes +``` + +The upgrade will occur automatically at height 200. Note: you may need to change the upgrade height in the snippet above if your test play takes more time. diff --git a/versioned_docs/version-0.47/integrate/tooling/02-confix.md b/versioned_docs/version-0.47/integrate/tooling/02-confix.md new file mode 100644 index 000000000..19c637ba9 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/tooling/02-confix.md @@ -0,0 +1,130 @@ +--- +sidebar_position: 1 +--- + +# Confix + +`Confix` is a configuration management tool that allows you to manage your configuration via CLI. + +It is based on the [CometBFT RFC 019](https://github.com/cometbft/cometbft/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md). + +## Installation + +### Add Config Command + +To add the confix tool, it's required to add the `ConfigCommand` to your application's root command file (e.g. `simd/cmd/root.go`). + +Import the `confixCmd` package: + +```go +import "cosmossdk.io/tools/confix/cmd" +``` + +Find the following line: + +```go +initRootCmd(rootCmd, encodingConfig) +``` + +After that line, add the following: + +```go +rootCmd.AddCommand( + confixcmd.ConfigCommand(), +) +``` + +The `ConfixCommand` function builds the `config` root command and is defined in the `confixCmd` package (`cosmossdk.io/tools/confix/cmd`). +An implementation example can be found in `simapp`. + +The command will be available as `simd config`. + +### Using Confix Standalone + +To use Confix standalone, without having to add it in your application, install it with the following command: + +```bash +go install cosmossdk.io/tools/confix/cmd/confix@latest +``` + +:::warning +Currently, due to the replace directive in the Confix go.mod, it is not possible to use `go install`. +Building from source or importing in an application is required until that replace directive is removed. +::: + +Alternatively, for building from source, simply run `make confix`. The binary will be located in `tools/confix`. + +## Usage + +Use standalone: + +```shell +confix --help +``` + +Use in simd: + +```shell +simd config fix --help +``` + +### Get + +Get a configuration value, e.g.: + +```shell +simd config get app pruning # gets the value pruning from app.toml +simd config get client chain-id # gets the value chain-id from client.toml +``` + +```shell +confix get ~/.simapp/config/app.toml pruning # gets the value pruning from app.toml +confix get ~/.simapp/config/client.toml chain-id # gets the value chain-id from client.toml +``` + +### Set + +Set a configuration value, e.g.: + +```shell +simd config set app pruning "enabled" # sets the value pruning from app.toml +simd config set client chain-id "foo-1" # sets the value chain-id from client.toml +``` + +```shell +confix set ~/.simapp/config/app.toml pruning "enabled" # sets the value pruning from app.toml +confix set ~/.simapp/config/client.toml chain-id "foo-1" # sets the value chain-id from client.toml +``` + +### Migrate + +Migrate a configuration file to a new version, e.g.: + +```shell +simd config migrate v0.47 # migrates defaultHome/config/app.toml to the latest v0.47 config +``` + +```shell +confix migrate v0.47 ~/.simapp/config/app.toml # migrate ~/.simapp/config/app.toml to the latest v0.47 config +``` + +### Diff + +Get the diff between a given configuration file and the default configuration file, e.g.: + +```shell +simd config diff v0.47 # gets the diff between defaultHome/config/app.toml and the latest v0.47 config +``` + +```shell +confix diff v0.47 ~/.simapp/config/app.toml # gets the diff between ~/.simapp/config/app.toml and the latest v0.47 config +``` + +### Maintainer + +At each SDK modification of the default configuration, add the default SDK config under `data/v0.XX-app.toml`. +This allows users to use the tool standalone. + +## Credits + +This project is based on the [CometBFT RFC 019](https://github.com/cometbft/cometbft/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md) and their own implementation of [confix](https://github.com/cometbft/cometbft/blob/v0.36.x/scripts/confix/confix.go). diff --git a/versioned_docs/version-0.47/integrate/building-modules/10-autocli.md b/versioned_docs/version-0.47/integrate/tooling/03-autocli.md similarity index 97% rename from versioned_docs/version-0.47/integrate/building-modules/10-autocli.md rename to versioned_docs/version-0.47/integrate/tooling/03-autocli.md index 1629e3d65..5b50774c0 100644 --- a/versioned_docs/version-0.47/integrate/building-modules/10-autocli.md +++ b/versioned_docs/version-0.47/integrate/tooling/03-autocli.md @@ -13,7 +13,7 @@ This document details how to build CLI and REST interfaces for a module. Example ## Pre-requisite Readings -* [Building Modules Intro](./01-intro.md) +* [Building Modules Intro](../building-modules/00-intro.md) ::: @@ -24,7 +24,7 @@ The `autocli` package is a [Go library](https://pkg.go.dev/cosmossdk.io/client/v Here are the steps to use the `autocli` package: 1. Define your app's modules that implement the `appmodule.AppModule` interface. -2. (optional) When willing to configure how behave `autocli` command generation, implement the `func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions` method on the module. Learn more [here](#advanced-usage). +2. Configure how behave `autocli` command generation, by implementing the `func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions` method on the module. Learn more [here](#advanced-usage). 3. Use the `autocli.AppOptions` struct to specifies the modules you defined. If you are using the `depinject` package to manage your app's dependencies, it can automatically create an instance of `autocli.AppOptions` based on your app's configuration. 4. Use the `EnhanceRootCommand()` method provided by `autocli` to add the CLI commands for the specified modules to your root command and can also be found in the `client/v2/autocli/app.go` file. Additionally, this method adds the `autocli` functionality to your app's root command. This method is additive only, meaning that it does not create commands if they are already registered for a module. Instead, it adds any missing commands to the root command. diff --git a/versioned_docs/version-0.47/integrate/tooling/04-hubl.md b/versioned_docs/version-0.47/integrate/tooling/04-hubl.md new file mode 100644 index 000000000..97d02921d --- /dev/null +++ b/versioned_docs/version-0.47/integrate/tooling/04-hubl.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 1 +--- + +# Hubl + +`Hubl` is a tool that allows you to query any Cosmos SDK based blockchain. +It takes advantage of the new [AutoCLI](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/client/v2@v2.0.0-20220916140313-c5245716b516/cli) feature of the Cosmos SDK. + +## Installation + +Hubl can be installed using `go install`: + +```shell +go install cosmossdk.io/tools/hubl/cmd/hubl@latest +``` + +Or build from source: + +```shell +git clone --depth=1 https://github.com/cosmos/cosmos-sdk +make hubl +``` + +The binary will be located in `tools/hubl`. + +## Usage + +```shell +hubl --help +``` + +### Add chain + +To configure a new chain just run this command using the --init flag and the name of the chain as it's listed in the chain registry (). + +If the chain is not listed in the chain registry, you can use any unique name. + +```shell +hubl init [chain-name] +hubl init regen +``` + +The chain configuration is stored in `~/.hubl/config.toml`. + +:::tip + +When using an unsecure gRPC endpoint, change the `insecure` field to `true` in the config file. + +```toml +[chains] +[chains.regen] +[[chains.regen.trusted-grpc-endpoints]] +endpoint = 'localhost:9090' +insecure = true +``` + +Or use the `--insecure` flag: + +```shell +hubl init regen --insecure +``` + +::: + +### Query + +To query a chain, you can use the `query` command. +Then specify which module you want to query and the query itself. + +```shell +hubl regen query auth module-accounts +``` diff --git a/versioned_docs/version-0.47/integrate/tooling/05-depinject.md b/versioned_docs/version-0.47/integrate/tooling/05-depinject.md new file mode 100644 index 000000000..17eb62872 --- /dev/null +++ b/versioned_docs/version-0.47/integrate/tooling/05-depinject.md @@ -0,0 +1,169 @@ +--- +sidebar_position: 1 +--- + +# Depinject + +> **DISCLAIMER**: This is a **beta** package. The SDK team is actively working on this feature and we are looking for feedback from the community. Please try it out and let us know what you think. + +## Overview + +`depinject` is a dependency injection framework for the Cosmos SDK. This module together with `core/appconfig` are meant to simplify the definition of a blockchain by replacing most of `app.go`'s boilerplate code with a configuration file (Go, YAML or JSON). + +* [Go Doc](https://pkg.go.dev/cosmossdk.io/depinject) + +## Usage + +`depinject` includes an expressive and composable [Configuration API](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/depinject#Config). +A core configuration function is `Provide`. The example below demonstrates the registration of free **provider functions** via the `Provide` API. + + +```go +package main + +import ( + "fmt" + + "cosmossdk.io/depinject" +) + +type AnotherInt int + +func main() { + var ( + x int + y AnotherInt + ) + + fmt.Printf("Before (%v, %v)\n", x, y) + depinject.Inject( + depinject.Provide( + func() int { return 1 }, + func() AnotherInt { return AnotherInt(2) }, + ), + &x, + &y, + ) + fmt.Printf("After (%v, %v)\n", x, y) +} +``` + +Provider functions form the basis of the dependency tree, they are introspected then their inputs identified as dependencies and outputs as dependants, either for another provider function or state stored outside the DI container, as is the case of `&x` and `&y` above. + +### Interface type resolution + +`depinject` supports interface types as inputs to provider functions. In the SDK's case this pattern is used to decouple +`Keeper` dependencies between modules. For example `x/bank` expects an [AccountKeeper](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/x/bank/types#AccountKeeper) interface as [input to ProvideModule](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/module.go#L208-L260). + +Concretely `SimApp` uses the implementation in `x/auth`, but this design allows for this loose coupling to change. + +Given the following types: + +```go +package duck + +type Duck interface { + quack() +} + +type AlsoDuck interface { + quack() +} + +type Mallard struct{} +type Canvasback struct{} + +func (duck Mallard) quack() {} +func (duck Canvasback) quack() {} + +type Pond struct { + Duck AlsoDuck +} +``` + +This usage + +```go +var pond Pond + +depinject.Inject( + depinject.Provide( + func() Mallard { return Mallard{} }, + func(duck Duck) Pond { + return Pond{Duck: duck} + }), + &pond) +``` + +results in an *implicit* binding of `Duck` to `Mallard`. This works because there is only one implementation of `Duck` in the container. +However, adding a second provider of `Duck` will result in an error: + +```go +var pond Pond + +depinject.Inject( + depinject.Provide( + func() Mallard { return Mallard{} }, + func() Canvasback { return Canvasback{} }, + func(duck Duck) Pond { + return Pond{Duck: duck} + }), + &pond) +``` + +A specific binding preference for `Duck` is required. + +#### `BindInterface` API + +In the above situation registering a binding for a given interface binding may look like + +```go +depinject.Inject( + depinject.Configs( + depinject.BindInterface( + "duck.Duck", + "duck.Mallard"), + depinject.Provide( + func() Mallard { return Mallard{} }, + func() Canvasback { return Canvasback{} }, + func(duck Duck) APond { + return Pond{Duck: duck} + })), + &pond) +``` + +Now `depinject` has enough information to provide `Mallard` as an input to `APond`. + +### Full example in real app + +:::warning +When using `depinject.Inject`, the injected types must be pointers. +::: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/app_v2.go#L219-L244 +``` + +## Debugging + +Issues with resolving dependencies in the container can be done with logs and [Graphviz](https://graphviz.org) renderings of the container tree. +By default, whenever there is an error, logs will be printed to stderr and a rendering of the dependency graph in Graphviz DOT format will be saved to `debug_container.dot`. + +Here is an example Graphviz rendering of a successful build of a dependency graph: +![Graphviz Example](https://raw.githubusercontent.com/cosmos/cosmos-sdk/ff39d243d421442b400befcd959ec3ccd2525154/depinject/testdata/example.svg) + +Rectangles represent functions, ovals represent types, rounded rectangles represent modules and the single hexagon +represents the function which called `Build`. Black-colored shapes mark functions and types that were called/resolved +without an error. Gray-colored nodes mark functions and types that could have been called/resolved in the container but +were left unused. + +Here is an example Graphviz rendering of a dependency graph build which failed: +![Graphviz Error Example](https://raw.githubusercontent.com/cosmos/cosmos-sdk/ff39d243d421442b400befcd959ec3ccd2525154/depinject/testdata/example_error.svg) + +Graphviz DOT files can be converted into SVG's for viewing in a web browser using the `dot` command-line tool, ex: + +```txt +dot -Tsvg debug_container.dot > debug_container.svg +``` + +Many other tools including some IDEs support working with DOT files. diff --git a/versioned_docs/version-0.47/integrate/tooling/README.md b/versioned_docs/version-0.47/integrate/tooling/README.md deleted file mode 100644 index c8b3af88d..000000000 --- a/versioned_docs/version-0.47/integrate/tooling/README.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -sidebar_position: 0 ---- - -# Tools - -This section provides documentation on various tooling used in development of a Cosmos SDK chain, operating a node and testing. - -* [Protocol Buffers](./00-protobuf.md) -* [Cosmovisor](./01-cosmovisor.md) -* [Depinject](./02-depinject.md) diff --git a/versioned_docs/version-0.47/integrate/tooling/_category_.json b/versioned_docs/version-0.47/integrate/tooling/_category_.json index d91e08b5a..a01a4fcc4 100644 --- a/versioned_docs/version-0.47/integrate/tooling/_category_.json +++ b/versioned_docs/version-0.47/integrate/tooling/_category_.json @@ -1,5 +1,5 @@ { "label": "Tooling", - "position": 9, + "position": 10, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/user/run-node/00-keyring.md b/versioned_docs/version-0.47/user/run-node/00-keyring.md index 2cb15b115..6bf2beed1 100644 --- a/versioned_docs/version-0.47/user/run-node/00-keyring.md +++ b/versioned_docs/version-0.47/user/run-node/00-keyring.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Setting up the keyring :::note Synopsis -This document describes how to configure and use the keyring and its various backends for an [**application**](../basics/00-app-anatomy.md). +This document describes how to configure and use the keyring and its various backends for an [**application**](../../develop/high-level-concepts/00-overview-app.md). ::: The keyring holds the private/public keypairs used to interact with a node. For instance, a validator key needs to be set up before running the blockchain node, so that blocks can be correctly signed. The private key can be stored in different locations, called "backends", such as a file or the operating system's own key storage. diff --git a/versioned_docs/version-0.47/user/run-node/01-run-node.md b/versioned_docs/version-0.47/user/run-node/01-run-node.md index a04038027..289ce28b6 100644 --- a/versioned_docs/version-0.47/user/run-node/01-run-node.md +++ b/versioned_docs/version-0.47/user/run-node/01-run-node.md @@ -12,8 +12,8 @@ Now that the application is ready and the keyring populated, it's time to see ho ### Pre-requisite Readings -* [Anatomy of a Cosmos SDK Application](../basics/00-app-anatomy.md) -* [Setting up the keyring](./00-keyring.md) +* [Anatomy of a Cosmos SDK Application](../../develop/high-level-concepts/00-overview-app.md) +* [Setting up the keyring](00-keyring.md) ::: @@ -74,7 +74,7 @@ A commonly used tool for this is [nginx](https://nginx.org). ## Adding Genesis Accounts -Before starting the chain, you need to populate the state with at least one account. To do so, first [create a new account in the keyring](./00-keyring.md#adding-keys-to-the-keyring) named `my_validator` under the `test` keyring backend (feel free to choose another name and another backend). +Before starting the chain, you need to populate the state with at least one account. To do so, first [create a new account in the keyring](00-keyring.md#adding-keys-to-the-keyring) named `my_validator` under the `test` keyring backend (feel free to choose another name and another backend). Now that you have created a local account, go ahead and grant it some `stake` tokens in your chain's genesis file. Doing so will also make sure your chain is aware of this account's existence: @@ -82,9 +82,9 @@ Now that you have created a local account, go ahead and grant it some `stake` to simd genesis add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake ``` -Recall that `$MY_VALIDATOR_ADDRESS` is a variable that holds the address of the `my_validator` key in the [keyring](./00-keyring.md#adding-keys-to-the-keyring). Also note that the tokens in the Cosmos SDK have the `{amount}{denom}` format: `amount` is is a 18-digit-precision decimal number, and `denom` is the unique token identifier with its denomination key (e.g. `atom` or `uatom`). Here, we are granting `stake` tokens, as `stake` is the token identifier used for staking in [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp). For your own chain with its own staking denom, that token identifier should be used instead. +Recall that `$MY_VALIDATOR_ADDRESS` is a variable that holds the address of the `my_validator` key in the [keyring](00-keyring.md#adding-keys-to-the-keyring). Also note that the tokens in the Cosmos SDK have the `{amount}{denom}` format: `amount` is is a 18-digit-precision decimal number, and `denom` is the unique token identifier with its denomination key (e.g. `atom` or `uatom`). Here, we are granting `stake` tokens, as `stake` is the token identifier used for staking in [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp). For your own chain with its own staking denom, that token identifier should be used instead. -Now that your account has some tokens, you need to add a validator to your chain. Validators are special full-nodes that participate in the consensus process (implemented in the [underlying consensus engine](../intro/02-sdk-app-architecture.md#cometbft)) in order to add new blocks to the chain. Any account can declare its intention to become a validator operator, but only those with sufficient delegation get to enter the active set (for example, only the top 125 validator candidates with the most delegation get to be validators in the Cosmos Hub). For this guide, you will add your local node (created via the `init` command above) as a validator of your chain. Validators can be declared before a chain is first started via a special transaction included in the genesis file called a `gentx`: +Now that your account has some tokens, you need to add a validator to your chain. Validators are special full-nodes that participate in the consensus process (implemented in the [underlying consensus engine](../../develop/intro/02-sdk-app-architecture.md#cometbft)) in order to add new blocks to the chain. Any account can declare its intention to become a validator operator, but only those with sufficient delegation get to enter the active set (for example, only the top 125 validator candidates with the most delegation get to be validators in the Cosmos Hub). For this guide, you will add your local node (created via the `init` command above) as a validator of your chain. Validators can be declared before a chain is first started via a special transaction included in the genesis file called a `gentx`: ```bash # Create a gentx. @@ -149,44 +149,3 @@ In config.toml: ```toml log_level: "state:info,p2p:info,consensus:info,x/staking:info,x/ibc:info,*error" ``` - -## State Sync - -State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.37/core/state-sync). - -State sync works thanks to snapshots. Read how the SDK handles snapshots [here](https://github.com/cosmos/cosmos-sdk/blob/825245d/store/snapshots/README.md). - -### Local State Sync - -Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. - -1. As mentioned in https://docs.cometbft.com/v0.37/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). -2. Run ` ` to restore a local snapshot (note: first load it from a file with the *load* command). -3. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` comet bootstrap-state` - -### Snapshots Commands - -The Cosmos SDK provides commands for managing snapshots. -These commands can be added in an app with the following snippet in `cmd//root.go`: - -```go -import ( - "github.com/cosmos/cosmos-sdk/client/snapshot" -) - -func initRootCmd(/* ... */) { - // ... - rootCmd.AddCommand( - snapshot.Cmd(appCreator), - ) -} -``` - -Then following commands are available at ` snapshots [command]`: - -* **list**: list local snapshots -* **load**: Load a snapshot archive file into snapshot store -* **restore**: Restore app state from local snapshot -* **export**: Export app state to snapshot store -* **dump**: Dump the snapshot as portable archive format -* **delete**: Delete a local snapshot diff --git a/versioned_docs/version-0.47/user/run-node/02-interact-node.md b/versioned_docs/version-0.47/user/run-node/02-interact-node.md index aaade7bce..8215becff 100644 --- a/versioned_docs/version-0.47/user/run-node/02-interact-node.md +++ b/versioned_docs/version-0.47/user/run-node/02-interact-node.md @@ -12,8 +12,8 @@ There are multiple ways to interact with a node: using the CLI, using gRPC or us ### Pre-requisite Readings -* [gRPC, REST and CometBFT Endpoints](../core/06-grpc_rest.md) -* [Running a Node](./01-run-node.md) +* [gRPC, REST and CometBFT Endpoints](../../develop/advanced-concepts/09-grpc_rest.md) +* [Running a Node](01-run-node.md) ::: @@ -56,7 +56,7 @@ You should see two delegations, the first one made from the `gentx`, and the sec ## Using gRPC -The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/06-grpc_rest.md). +The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../../develop/advanced-concepts/09-grpc_rest.md). Since the code generation library largely depends on your own tech stack, we will only present three alternatives: @@ -68,7 +68,7 @@ Since the code generation library largely depends on your own tech stack, we wil [grpcurl](https://github.com/fullstorydev/grpcurl) is like `curl` but for gRPC. It is also available as a Go library, but we will use it only as a CLI command for debugging and testing purposes. Follow the instructions in the previous link to install it. -Assuming you have a local node running (either a localnet, or connected a live network), you should be able to run the following command to list the Protobuf services available (you can replace `localhost:9000` by the gRPC server endpoint of another node, which is configured under the `grpc.address` field inside [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml)): +Assuming you have a local node running (either a localnet, or connected a live network), you should be able to run the following command to list the Protobuf services available (you can replace `localhost:9000` by the gRPC server endpoint of another node, which is configured under the `grpc.address` field inside [`app.toml`](01-run-node.md#configuring-the-node-using-apptoml-and-configtoml)): ```bash grpcurl -plaintext localhost:9090 list @@ -250,7 +250,7 @@ CosmJS documentation can be found at [https://cosmos.github.io/cosmjs](https://c ## Using the REST Endpoints -As described in the [gRPC guide](../core/06-grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. +As described in the [gRPC guide](../../develop/advanced-concepts/09-grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. Note that the REST endpoints are not enabled by default. To enable them, edit the `api` section of your `~/.simapp/config/app.toml` file: @@ -270,7 +270,7 @@ curl \ Make sure to replace `localhost:1317` with the REST endpoint of your node, configured under the `api.address` field. -The list of all available REST endpoints is available as a Swagger specification file, it can be viewed at `localhost:1317/swagger`. Make sure that the `api.swagger` field is set to true in your [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml) file. +The list of all available REST endpoints is available as a Swagger specification file, it can be viewed at `localhost:1317/swagger`. Make sure that the `api.swagger` field is set to true in your [`app.toml`](01-run-node.md#configuring-the-node-using-apptoml) file. ### Query for historical state using REST @@ -288,4 +288,4 @@ Assuming the state at that block has not yet been pruned by the node, this query ### Cross-Origin Resource Sharing (CORS) -[CORS policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `enabled-unsafe-cors` field inside [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml). +[CORS policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `enabled-unsafe-cors` field inside [`app.toml`](01-run-node.md#configuring-the-node-using-apptoml). diff --git a/versioned_docs/version-0.47/user/run-node/03-txs.md b/versioned_docs/version-0.47/user/run-node/03-txs.md index c8d2b610b..9e9061698 100644 --- a/versioned_docs/version-0.47/user/run-node/03-txs.md +++ b/versioned_docs/version-0.47/user/run-node/03-txs.md @@ -10,7 +10,7 @@ This document describes how to generate an (unsigned) transaction, signing it (w ## Using the CLI -The easiest way to send transactions is using the CLI, as we have seen in the previous page when [interacting with a node](./02-interact-node.md#using-the-cli). For example, running the following command +The easiest way to send transactions is using the CLI, as we have seen in the previous page when [interacting with a node](02-interact-node.md#using-the-cli). For example, running the following command ```bash simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --keyring-backend test @@ -20,7 +20,7 @@ will run the following steps: * generate a transaction with one `Msg` (`x/bank`'s `MsgSend`), and print the generated transaction to the console. * ask the user for confirmation to send the transaction from the `$MY_VALIDATOR_ADDRESS` account. -* fetch `$MY_VALIDATOR_ADDRESS` from the keyring. This is possible because we have [set up the CLI's keyring](./00-keyring.md) in a previous step. +* fetch `$MY_VALIDATOR_ADDRESS` from the keyring. This is possible because we have [set up the CLI's keyring](00-keyring.md) in a previous step. * sign the generated transaction with the keyring's account. * broadcast the signed transaction to the network. This is possible because the CLI connects to the node's CometBFT RPC endpoint. @@ -269,7 +269,7 @@ func sendTx() error { ### Broadcasting a Transaction -The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the CometBFT RPC is also posible. An overview of the differences between these methods is exposed [here](../core/06-grpc_rest.md). For this tutorial, we will only describe the gRPC method. +The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the CometBFT RPC is also posible. An overview of the differences between these methods is exposed [here](../../develop/advanced-concepts/09-grpc_rest.md). For this tutorial, we will only describe the gRPC method. ```go import ( diff --git a/versioned_docs/version-0.47/user/run-node/04-rosetta.md b/versioned_docs/version-0.47/user/run-node/04-rosetta.md new file mode 100644 index 000000000..3d8467aea --- /dev/null +++ b/versioned_docs/version-0.47/user/run-node/04-rosetta.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 1 +--- + +# Rosetta + +The `rosetta` package implements Coinbase's [Rosetta API](https://www.rosetta-api.org). This document provides instructions on how to use the Rosetta API integration. For information about the motivation and design choices, refer to [ADR 035](https://docs.cosmos.network/main/architecture/adr-035-rosetta-api-support). + +## Add Rosetta Command + +The Rosetta API server is a stand-alone server that connects to a node of a chain developed with Cosmos SDK. + +To enable Rosetta API support, it's required to add the `RosettaCommand` to your application's root command file (e.g. `simd/cmd/root.go`). + +Import the `rosettaCmd` package: + +```go +import "cosmossdk.io/tools/rosetta/cmd" +``` + +Find the following line: + +```go +initRootCmd(rootCmd, encodingConfig) +``` + +After that line, add the following: + +```go +rootCmd.AddCommand( + rosettaCmd.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec) +) +``` + +The `RosettaCommand` function builds the `rosetta` root command and is defined in the `rosettaCmd` package (`cosmossdk.io/tools/rosetta/cmd`). + +Since we’ve updated the Cosmos SDK to work with the Rosetta API, updating the application's root command file is all you need to do. + +An implementation example can be found in `simapp` package. + +## Use Rosetta Command + +To run Rosetta in your application CLI, use the following command: + +```shell +simd rosetta --help +``` + +To test and run Rosetta API endpoints for applications that are running and exposed, use the following command: + +```shell +simd rosetta + --blockchain "your application name (ex: gaia)" + --network "your chain identifier (ex: testnet-1)" + --tendermint "tendermint endpoint (ex: localhost:26657)" + --grpc "gRPC endpoint (ex: localhost:9090)" + --addr "rosetta binding address (ex: :8080)" +``` + +## Use Rosetta Standalone + +To use Rosetta standalone, without having to add it in your application, install it with the following command: + +```bash +go install cosmossdk.io/tools/rosetta/cmd/rosetta +``` + +Alternatively, for building from source, simply run `make rosetta`. The binary will be located in `tools/rosetta`. + +## Extensions + +There are two ways in which you can customize and extend the implementation with your custom settings. + +### Message extension + +In order to make an `sdk.Msg` understandable by rosetta the only thing which is required is adding the methods to your messages that satisfy the `rosetta.Msg` interface. Examples on how to do so can be found in the staking types such as `MsgDelegate`, or in bank types such as `MsgSend`. + +### Client interface override + +In case more customization is required, it's possible to embed the Client type and override the methods which require customizations. + +Example: + +```go +package custom_client +import ( + +"context" +"github.com/coinbase/rosetta-sdk-go/types" +"cosmossdk.io/tools/rosetta/lib" +) + +// CustomClient embeds the standard cosmos client +// which means that it implements the cosmos-rosetta-gateway Client +// interface while at the same time allowing to customize certain methods +type CustomClient struct { + *rosetta.Client +} + +func (c *CustomClient) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // provide custom signature bytes + panic("implement me") +} +``` + +NOTE: when using a customized client, the command cannot be used as the constructors required **may** differ, so it's required to create a new one. We intend to provide a way to init a customized client without writing extra code in the future. + +### Error extension + +Since rosetta requires to provide 'returned' errors to network options. In order to declare a new rosetta error, we use the `errors` package in cosmos-rosetta-gateway. + +Example: + +```go +package custom_errors +import crgerrs "cosmossdk.io/tools/rosetta/lib/errors" + +var customErrRetriable = true +var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description") +``` + +Note: errors must be registered before cosmos-rosetta-gateway's `Server`.`Start` method is called. Otherwise the registration will be ignored. Errors with same code will be ignored too. diff --git a/versioned_docs/version-0.47/user/run-node/06-run-production.md b/versioned_docs/version-0.47/user/run-node/06-run-production.md index 9af61725b..31d2932e0 100644 --- a/versioned_docs/version-0.47/user/run-node/06-run-production.md +++ b/versioned_docs/version-0.47/user/run-node/06-run-production.md @@ -72,6 +72,7 @@ or ```bash sudo ufw allow 22 ``` + Both of the above commands are the same. 3. Allow Port 26656 (cometbft p2p port). If the node has a modified p2p port then that port must be used here. @@ -166,6 +167,7 @@ cargo install tmkms --features=softsign tmkms init config tmkms softsign keygen ./config/secrets/secret_connection_key ``` + or Cargo install: @@ -253,6 +255,7 @@ It is recommended to comment or delete the lines that specify the path of the va # Path to the JSON file containing the last sign state of a validator # priv_validator_state_file = "data/priv_validator_state.json" ``` + ::: 6. Start the two processes. diff --git a/versioned_docs/version-0.47/user/run-node/_category_.json b/versioned_docs/version-0.47/user/run-node/_category_.json index 375a7c423..9b291ba6f 100644 --- a/versioned_docs/version-0.47/user/run-node/_category_.json +++ b/versioned_docs/version-0.47/user/run-node/_category_.json @@ -1,5 +1,5 @@ { - "label": "Running a Node, API and CLI", - "position": 5, + "label": "User Guides", + "position": 0, "link": null } \ No newline at end of file diff --git a/versioned_docs/version-0.47/user/run-node/05-run-testnet.md b/versioned_docs/version-0.47/validate/05-run-testnet.md similarity index 92% rename from versioned_docs/version-0.47/user/run-node/05-run-testnet.md rename to versioned_docs/version-0.47/validate/05-run-testnet.md index c2b5da598..e9a06ed34 100644 --- a/versioned_docs/version-0.47/user/run-node/05-run-testnet.md +++ b/versioned_docs/version-0.47/validate/05-run-testnet.md @@ -8,7 +8,7 @@ sidebar_position: 1 The `simd testnet` subcommand makes it easy to initialize and start a simulated test network for testing purposes. ::: -In addition to the commands for [running a node](./01-run-node.md), the `simd` binary also includes a `testnet` command that allows you to start a simulated test network in-process or to initialize files for a simulated test network that runs in a separate process. +In addition to the commands for [running a node](../user/run-node/01-run-node.md), the `simd` binary also includes a `testnet` command that allows you to start a simulated test network in-process or to initialize files for a simulated test network that runs in a separate process. ## Initialize Files