From addcfbf5cb197e74fc2fd5aebef4b5d2a8847ada Mon Sep 17 00:00:00 2001 From: gamarin2 Date: Wed, 14 Nov 2018 20:44:17 +0100 Subject: [PATCH] Documentation Structure Change and Cleanup (#2808) * Update docs/sdk/clients.md * organize ADR directory like tendermint * docs: move spec-proposals into spec/ * remove lotion, moved to website repo * move getting-started to cosmos-hub, and voyager to website * docs: move lite/ into clients/lite/ * move introduction/ content to website repo * move resources/ content to website repo * mv sdk/clients.md to clients/clients.md * mv validators to cosmos-hub/validators * move deprecated sdk/ content to _attic * sdk/modules.md is duplicate with modules/README.md * consolidate remianing sdk/ files into a single sdk.md * move examples/ to docs/examples/ * mv docs/cosmos-hub to docs/gaia * Add keys/accounts section to localnet docs --- CHANGELOG.md | 2 + Makefile | 28 +- README.md | 17 +- cmd/cosmos-sdk-cli/cmd/init.go | 2 +- docs/.vuepress/config.js | 106 +- docs/DOCS_README.md | 26 +- docs/README.md | 40 +- docs/{clients => _attic}/node.md | 0 docs/{ => _attic}/sdk/core/app1.md | 0 docs/{ => _attic}/sdk/core/app2.md | 0 docs/{ => _attic}/sdk/core/app3.md | 0 docs/{ => _attic}/sdk/core/app4.md | 0 docs/{ => _attic}/sdk/core/app5.md | 0 docs/{ => _attic}/sdk/core/examples/app1.go | 0 docs/{ => _attic}/sdk/core/examples/app2.go | 0 .../sdk/core/examples/app2_test.go | 0 docs/{ => _attic}/sdk/core/examples/app3.go | 0 docs/{ => _attic}/sdk/core/examples/app4.go | 0 .../sdk/core/examples/app4_test.go | 0 docs/{ => _attic}/sdk/core/intro.md | 0 docs/{ => _attic}/sdk/core/multistore.md | 0 .../{ => _attic}/sdk/sdk-by-examples/intro.md | 0 .../simple-governance/app-init.md | 0 .../simple-governance/bridging-it-all.md | 0 .../simple-governance/intro.md | 0 .../running-the-application.md | 0 .../simple-governance/setup-and-design.md | 0 .../simple-governance/simple-gov-module.md | 0 docs/architecture/adr-002-docs-structure.md | 94 + docs/architecture/decision-records/README.md | 22 - .../adr-001-message-counter.md | 54 - .../decision-records/adr-template.md | 32 - docs/clients/README.md | 18 + docs/clients/cli.md | 7 +- docs/{ => clients}/lite/getting_started.md | 4 +- docs/{ => clients}/lite/pics/C2H.png | Bin docs/{ => clients}/lite/pics/H2C.png | Bin docs/{ => clients}/lite/pics/MA.png | Bin docs/{ => clients}/lite/pics/absence1.png | Bin docs/{ => clients}/lite/pics/absence2.png | Bin docs/{ => clients}/lite/pics/absence3.png | Bin docs/{ => clients}/lite/pics/architecture.png | Bin .../{ => clients}/lite/pics/changeProcess.png | Bin .../lite/pics/commitValidation.png | Bin .../lite/pics/create-account.png | Bin docs/{ => clients}/lite/pics/deposit.png | Bin docs/{ => clients}/lite/pics/existProof.png | Bin docs/{ => clients}/lite/pics/high-level.png | Bin .../lite/pics/light-client-architecture.png | Bin .../lite/pics/loadbalanceDiagram.png | Bin .../lite/pics/simpleMerkleTree.png | Bin .../{ => clients}/lite/pics/substoreProof.png | Bin .../lite/pics/transfer-tokens.png | Bin docs/{ => clients}/lite/pics/transfer.png | Bin .../lite/pics/trustPropagate.png | Bin .../lite/pics/updateValidatorToHeight.png | Bin .../lite/pics/validatorSetChange.png | Bin docs/{ => clients}/lite/pics/withdraw.png | Bin docs/{ => clients}/lite/readme.md | 52 +- docs/{ => clients}/lite/specification.md | 14 +- docs/clients/rest.md | 6 - docs/clients/service-providers.md | 6 +- docs/{graphics => }/cosmos-docs.jpg | Bin {examples => docs/examples}/README.md | 0 .../examples}/basecoin/app/app.go | 2 +- .../examples}/basecoin/app/app_test.go | 2 +- .../examples}/basecoin/cli_test/cli_test.go | 0 .../examples}/basecoin/cmd/basecli/main.go | 4 +- .../examples}/basecoin/cmd/basecoind/main.go | 2 +- .../examples}/basecoin/types/account.go | 0 .../examples}/democoin/app/app.go | 10 +- .../examples}/democoin/app/app_test.go | 4 +- .../examples}/democoin/cli_test/cli_test.go | 0 .../examples}/democoin/cmd/democli/main.go | 10 +- .../examples}/democoin/cmd/democoind/main.go | 2 +- .../examples}/democoin/mock/validator.go | 0 .../examples}/democoin/types/account.go | 4 +- .../democoin/x/assoc/validator_set.go | 0 .../democoin/x/assoc/validator_set_test.go | 2 +- .../examples}/democoin/x/cool/app_test.go | 0 .../democoin/x/cool/client/cli/tx.go | 2 +- .../examples}/democoin/x/cool/codec.go | 0 .../examples}/democoin/x/cool/errors.go | 0 .../examples}/democoin/x/cool/handler.go | 0 .../examples}/democoin/x/cool/keeper.go | 0 .../examples}/democoin/x/cool/keeper_test.go | 0 .../examples}/democoin/x/cool/types.go | 0 .../examples}/democoin/x/oracle/README.md | 0 .../examples}/democoin/x/oracle/errors.go | 0 .../examples}/democoin/x/oracle/handler.go | 0 .../examples}/democoin/x/oracle/keeper.go | 0 .../democoin/x/oracle/keeper_keys.go | 0 .../democoin/x/oracle/oracle_test.go | 2 +- .../examples}/democoin/x/oracle/types.go | 0 .../examples}/democoin/x/pow/app_test.go | 0 .../examples}/democoin/x/pow/client/cli/tx.go | 2 +- .../examples}/democoin/x/pow/codec.go | 0 .../examples}/democoin/x/pow/errors.go | 0 .../examples}/democoin/x/pow/handler.go | 0 .../examples}/democoin/x/pow/handler_test.go | 0 .../examples}/democoin/x/pow/keeper.go | 0 .../examples}/democoin/x/pow/keeper_test.go | 0 .../examples}/democoin/x/pow/mine.go | 0 .../examples}/democoin/x/pow/types.go | 0 .../examples}/democoin/x/pow/types_test.go | 0 .../x/simplestake/client/cli/commands.go | 2 +- .../examples}/democoin/x/simplestake/codec.go | 0 .../democoin/x/simplestake/errors.go | 0 .../democoin/x/simplestake/handler.go | 0 .../democoin/x/simplestake/keeper.go | 0 .../democoin/x/simplestake/keeper_test.go | 0 .../examples}/democoin/x/simplestake/msgs.go | 0 .../democoin/x/simplestake/msgs_test.go | 0 .../examples}/democoin/x/simplestake/types.go | 0 .../examples}/democoin/x/sketchy/handler.go | 0 {examples => docs/examples}/kvstore/kvstore | Bin {examples => docs/examples}/kvstore/main.go | 0 {examples => docs/examples}/kvstore/tx.go | 0 docs/gaia/README.md | 19 + docs/{sdk/clients.md => gaia/gaiacli.md} | 138 +- .../{getting-started => gaia}/installation.md | 18 +- .../{getting-started => gaia}/join-testnet.md | 36 +- docs/{clients => gaia}/keys.md | 0 docs/{clients => gaia}/ledger.md | 0 docs/{getting-started => gaia}/networks.md | 26 +- docs/{ => gaia}/validators/overview.md | 0 docs/{ => gaia}/validators/security.md | 0 docs/{ => gaia}/validators/validator-faq.md | 0 docs/{ => gaia}/validators/validator-setup.md | 24 +- docs/getting-started/voyager.md | 9 - docs/graphics/cosmos-sdk-image.png | Bin 190395 -> 0 bytes docs/intro/README.md | 43 + docs/intro/ocap.md | 102 ++ docs/intro/sdk-app-architecture.md | 62 + docs/introduction/cosmos-hub.md | 32 - docs/introduction/tendermint-cosmos.md | 27 - docs/introduction/tendermint.md | 47 - docs/introduction/what-is-cosmos.md | 7 - docs/lotion/overview.md | 54 - docs/reference/baseapp.md | 14 + docs/reference/store/README.md | 0 docs/resources/delegator-faq.md | 69 - docs/resources/diagrams/todo.md | 17 - docs/resources/faq.md | 95 - docs/resources/whitepaper-ko.md | 756 -------- docs/resources/whitepaper-pt.md | 1482 --------------- docs/resources/whitepaper-zh-CN.md | 1013 ----------- docs/resources/whitepaper.md | 1590 ----------------- docs/sdk/cosmos-sdk-cli.md | 34 - docs/sdk/modules.md | 19 - docs/sdk/overview.md | 205 --- docs/spec/README.md | 43 +- .../{ => spec}/ics/ics-030-signed-messages.md | 0 .../f1-fee-distribution/f1_fee_distr.pdf | Bin .../f1-fee-distribution/f1_fee_distr.tex | 0 x/gov/client/cli/tx.go | 2 +- 156 files changed, 665 insertions(+), 5898 deletions(-) rename docs/{clients => _attic}/node.md (100%) rename docs/{ => _attic}/sdk/core/app1.md (100%) rename docs/{ => _attic}/sdk/core/app2.md (100%) rename docs/{ => _attic}/sdk/core/app3.md (100%) rename docs/{ => _attic}/sdk/core/app4.md (100%) rename docs/{ => _attic}/sdk/core/app5.md (100%) rename docs/{ => _attic}/sdk/core/examples/app1.go (100%) rename docs/{ => _attic}/sdk/core/examples/app2.go (100%) rename docs/{ => _attic}/sdk/core/examples/app2_test.go (100%) rename docs/{ => _attic}/sdk/core/examples/app3.go (100%) rename docs/{ => _attic}/sdk/core/examples/app4.go (100%) rename docs/{ => _attic}/sdk/core/examples/app4_test.go (100%) rename docs/{ => _attic}/sdk/core/intro.md (100%) rename docs/{ => _attic}/sdk/core/multistore.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/intro.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/app-init.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/bridging-it-all.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/intro.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/running-the-application.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/setup-and-design.md (100%) rename docs/{ => _attic}/sdk/sdk-by-examples/simple-governance/simple-gov-module.md (100%) create mode 100644 docs/architecture/adr-002-docs-structure.md delete mode 100644 docs/architecture/decision-records/README.md delete mode 100644 docs/architecture/decision-records/adr-001-message-counter.md delete mode 100644 docs/architecture/decision-records/adr-template.md create mode 100644 docs/clients/README.md rename docs/{ => clients}/lite/getting_started.md (94%) rename docs/{ => clients}/lite/pics/C2H.png (100%) rename docs/{ => clients}/lite/pics/H2C.png (100%) rename docs/{ => clients}/lite/pics/MA.png (100%) rename docs/{ => clients}/lite/pics/absence1.png (100%) rename docs/{ => clients}/lite/pics/absence2.png (100%) rename docs/{ => clients}/lite/pics/absence3.png (100%) rename docs/{ => clients}/lite/pics/architecture.png (100%) rename docs/{ => clients}/lite/pics/changeProcess.png (100%) rename docs/{ => clients}/lite/pics/commitValidation.png (100%) rename docs/{ => clients}/lite/pics/create-account.png (100%) rename docs/{ => clients}/lite/pics/deposit.png (100%) rename docs/{ => clients}/lite/pics/existProof.png (100%) rename docs/{ => clients}/lite/pics/high-level.png (100%) rename docs/{ => clients}/lite/pics/light-client-architecture.png (100%) rename docs/{ => clients}/lite/pics/loadbalanceDiagram.png (100%) rename docs/{ => clients}/lite/pics/simpleMerkleTree.png (100%) rename docs/{ => clients}/lite/pics/substoreProof.png (100%) rename docs/{ => clients}/lite/pics/transfer-tokens.png (100%) rename docs/{ => clients}/lite/pics/transfer.png (100%) rename docs/{ => clients}/lite/pics/trustPropagate.png (100%) rename docs/{ => clients}/lite/pics/updateValidatorToHeight.png (100%) rename docs/{ => clients}/lite/pics/validatorSetChange.png (100%) rename docs/{ => clients}/lite/pics/withdraw.png (100%) rename docs/{ => clients}/lite/readme.md (58%) rename docs/{ => clients}/lite/specification.md (95%) delete mode 100644 docs/clients/rest.md rename docs/{graphics => }/cosmos-docs.jpg (100%) rename {examples => docs/examples}/README.md (100%) rename {examples => docs/examples}/basecoin/app/app.go (98%) rename {examples => docs/examples}/basecoin/app/app_test.go (97%) rename {examples => docs/examples}/basecoin/cli_test/cli_test.go (100%) rename {examples => docs/examples}/basecoin/cmd/basecli/main.go (95%) rename {examples => docs/examples}/basecoin/cmd/basecoind/main.go (98%) rename {examples => docs/examples}/basecoin/types/account.go (100%) rename {examples => docs/examples}/democoin/app/app.go (95%) rename {examples => docs/examples}/democoin/app/app_test.go (94%) rename {examples => docs/examples}/democoin/cli_test/cli_test.go (100%) rename {examples => docs/examples}/democoin/cmd/democli/main.go (86%) rename {examples => docs/examples}/democoin/cmd/democoind/main.go (98%) rename {examples => docs/examples}/democoin/mock/validator.go (100%) rename {examples => docs/examples}/democoin/types/account.go (94%) rename {examples => docs/examples}/democoin/x/assoc/validator_set.go (100%) rename {examples => docs/examples}/democoin/x/assoc/validator_set_test.go (97%) rename {examples => docs/examples}/democoin/x/cool/app_test.go (100%) rename {examples => docs/examples}/democoin/x/cool/client/cli/tx.go (96%) rename {examples => docs/examples}/democoin/x/cool/codec.go (100%) rename {examples => docs/examples}/democoin/x/cool/errors.go (100%) rename {examples => docs/examples}/democoin/x/cool/handler.go (100%) rename {examples => docs/examples}/democoin/x/cool/keeper.go (100%) rename {examples => docs/examples}/democoin/x/cool/keeper_test.go (100%) rename {examples => docs/examples}/democoin/x/cool/types.go (100%) rename {examples => docs/examples}/democoin/x/oracle/README.md (100%) rename {examples => docs/examples}/democoin/x/oracle/errors.go (100%) rename {examples => docs/examples}/democoin/x/oracle/handler.go (100%) rename {examples => docs/examples}/democoin/x/oracle/keeper.go (100%) rename {examples => docs/examples}/democoin/x/oracle/keeper_keys.go (100%) rename {examples => docs/examples}/democoin/x/oracle/oracle_test.go (98%) rename {examples => docs/examples}/democoin/x/oracle/types.go (100%) rename {examples => docs/examples}/democoin/x/pow/app_test.go (100%) rename {examples => docs/examples}/democoin/x/pow/client/cli/tx.go (95%) rename {examples => docs/examples}/democoin/x/pow/codec.go (100%) rename {examples => docs/examples}/democoin/x/pow/errors.go (100%) rename {examples => docs/examples}/democoin/x/pow/handler.go (100%) rename {examples => docs/examples}/democoin/x/pow/handler_test.go (100%) rename {examples => docs/examples}/democoin/x/pow/keeper.go (100%) rename {examples => docs/examples}/democoin/x/pow/keeper_test.go (100%) rename {examples => docs/examples}/democoin/x/pow/mine.go (100%) rename {examples => docs/examples}/democoin/x/pow/types.go (100%) rename {examples => docs/examples}/democoin/x/pow/types_test.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/client/cli/commands.go (97%) rename {examples => docs/examples}/democoin/x/simplestake/codec.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/errors.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/handler.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/keeper.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/keeper_test.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/msgs.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/msgs_test.go (100%) rename {examples => docs/examples}/democoin/x/simplestake/types.go (100%) rename {examples => docs/examples}/democoin/x/sketchy/handler.go (100%) rename {examples => docs/examples}/kvstore/kvstore (100%) rename {examples => docs/examples}/kvstore/main.go (100%) rename {examples => docs/examples}/kvstore/tx.go (100%) create mode 100644 docs/gaia/README.md rename docs/{sdk/clients.md => gaia/gaiacli.md} (88%) rename docs/{getting-started => gaia}/installation.md (51%) rename docs/{getting-started => gaia}/join-testnet.md (71%) rename docs/{clients => gaia}/keys.md (100%) rename docs/{clients => gaia}/ledger.md (100%) rename docs/{getting-started => gaia}/networks.md (89%) rename docs/{ => gaia}/validators/overview.md (100%) rename docs/{ => gaia}/validators/security.md (100%) rename docs/{ => gaia}/validators/validator-faq.md (100%) rename docs/{ => gaia}/validators/validator-setup.md (85%) delete mode 100644 docs/getting-started/voyager.md delete mode 100644 docs/graphics/cosmos-sdk-image.png create mode 100644 docs/intro/README.md create mode 100644 docs/intro/ocap.md create mode 100644 docs/intro/sdk-app-architecture.md delete mode 100644 docs/introduction/cosmos-hub.md delete mode 100644 docs/introduction/tendermint-cosmos.md delete mode 100644 docs/introduction/tendermint.md delete mode 100644 docs/introduction/what-is-cosmos.md delete mode 100644 docs/lotion/overview.md create mode 100644 docs/reference/baseapp.md create mode 100644 docs/reference/store/README.md delete mode 100644 docs/resources/delegator-faq.md delete mode 100644 docs/resources/diagrams/todo.md delete mode 100644 docs/resources/faq.md delete mode 100644 docs/resources/whitepaper-ko.md delete mode 100644 docs/resources/whitepaper-pt.md delete mode 100644 docs/resources/whitepaper-zh-CN.md delete mode 100644 docs/resources/whitepaper.md delete mode 100644 docs/sdk/cosmos-sdk-cli.md delete mode 100644 docs/sdk/modules.md delete mode 100644 docs/sdk/overview.md rename docs/{ => spec}/ics/ics-030-signed-messages.md (100%) rename docs/{ => spec}/spec-proposals/f1-fee-distribution/f1_fee_distr.pdf (100%) rename docs/{ => spec}/spec-proposals/f1-fee-distribution/f1_fee_distr.tex (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 425c2cf14426..50316b4a7299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -245,6 +245,7 @@ IMPROVEMENTS * [cli] [\#2128](https://github.com/cosmos/cosmos-sdk/issues/2128) fixed segfault when exporting directly after `gaiad init` * [cli] [\#1255](https://github.com/cosmos/cosmos-sdk/issues/1255) open KeyBase in read-only mode for query-purpose CLI commands + * [docs] Added commands for querying governance deposits, votes and tally * Gaia * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. @@ -289,6 +290,7 @@ BUG FIXES * Gaia * [x/stake] Return correct Tendermint validator update set on `EndBlocker` by not including non previously bonded validators that have zero power. [#2189](https://github.com/cosmos/cosmos-sdk/issues/2189) + * [docs] Fixed light client section links * SDK * [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) diff --git a/Makefile b/Makefile index 0f7c531b8c2d..35e5b50eff1f 100644 --- a/Makefile +++ b/Makefile @@ -66,15 +66,15 @@ endif build_examples: ifeq ($(OS),Windows_NT) - go build $(BUILD_FLAGS) -o build/basecoind.exe ./examples/basecoin/cmd/basecoind - go build $(BUILD_FLAGS) -o build/basecli.exe ./examples/basecoin/cmd/basecli - go build $(BUILD_FLAGS) -o build/democoind.exe ./examples/democoin/cmd/democoind - go build $(BUILD_FLAGS) -o build/democli.exe ./examples/democoin/cmd/democli + go build $(BUILD_FLAGS) -o build/basecoind.exe ./docs/examples/basecoin/cmd/basecoind + go build $(BUILD_FLAGS) -o build/basecli.exe ./docs/examples/basecoin/cmd/basecli + go build $(BUILD_FLAGS) -o build/democoind.exe ./docs/examples/democoin/cmd/democoind + go build $(BUILD_FLAGS) -o build/democli.exe ./docs/examples/democoin/cmd/democli else - go build $(BUILD_FLAGS) -o build/basecoind ./examples/basecoin/cmd/basecoind - go build $(BUILD_FLAGS) -o build/basecli ./examples/basecoin/cmd/basecli - go build $(BUILD_FLAGS) -o build/democoind ./examples/democoin/cmd/democoind - go build $(BUILD_FLAGS) -o build/democli ./examples/democoin/cmd/democli + go build $(BUILD_FLAGS) -o build/basecoind ./docs/examples/basecoin/cmd/basecoind + go build $(BUILD_FLAGS) -o build/basecli ./docs/examples/basecoin/cmd/basecli + go build $(BUILD_FLAGS) -o build/democoind ./docs/examples/democoin/cmd/democoind + go build $(BUILD_FLAGS) -o build/democli ./docs/examples/democoin/cmd/democli endif install: check-ledger update_gaia_lite_docs @@ -82,10 +82,10 @@ install: check-ledger update_gaia_lite_docs go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiacli install_examples: - go install $(BUILD_FLAGS) ./examples/basecoin/cmd/basecoind - go install $(BUILD_FLAGS) ./examples/basecoin/cmd/basecli - go install $(BUILD_FLAGS) ./examples/democoin/cmd/democoind - go install $(BUILD_FLAGS) ./examples/democoin/cmd/democli + go install $(BUILD_FLAGS) ./docs/examples/basecoin/cmd/basecoind + go install $(BUILD_FLAGS) ./docs/examples/basecoin/cmd/basecli + go install $(BUILD_FLAGS) ./docs/examples/democoin/cmd/democoind + go install $(BUILD_FLAGS) ./docs/examples/democoin/cmd/democli install_cosmos-sdk-cli: go install $(BUILD_FLAGS) ./cmd/cosmos-sdk-cli @@ -159,8 +159,8 @@ test_cli: @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test` -tags=cli_test test_examples: - @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/examples/basecoin/cli_test` -tags=cli_test - @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/examples/democoin/cli_test` -tags=cli_test + @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/docs/examples/basecoin/cli_test` -tags=cli_test + @go test -count 1 -p 1 `go list github.com/cosmos/cosmos-sdk/docs/examples/democoin/cli_test` -tags=cli_test test_unit: @VERSION=$(VERSION) go test $(PACKAGES_NOSIMULATION) diff --git a/README.md b/README.md index 94b2b19da848..b57cd1dff5f7 100644 --- a/README.md +++ b/README.md @@ -17,27 +17,26 @@ It is being used to build `Gaia`, the first implementation of the [Cosmos Hub](h **WARNING**: The SDK has mostly stabilized, but we are still making some breaking changes. -**Note**: Requires [Go 1.10+](https://golang.org/dl/) +**Note**: Requires [Go 1.11+](https://golang.org/dl/) ## Gaia Testnet +To install the binaries, read the [install instructions](./docs/gaia/installation.md) + To join the latest testnet, follow -[the guide](./docs/getting-started/join-testnet.md). +[the guide](./docs/gaia/join-testnet.md). For status updates and genesis files, see the [testnets repo](https://github.com/cosmos/testnets). -## Install - -See the -[install instructions](./docs/getting-started/installation.md). ## Quick Start -See the [Cosmos Docs](https://cosmos.network/docs/) +To learn how the SDK works from a high-level perspective, go to the [SDK Intro](./docs/intro/README.md). + +If you want to get started quickly and learn how to build on top of the SDK, please follow the [SDK Application Tutorial](https://github.com/cosmos/sdk-application-tutorial). You can also fork the tutorial's repo to get started building your own Cosmos SDK application. -- [Getting started with the SDK](./docs/sdk/core/intro.md) -- [SDK Examples](/examples) +For more, please go to the [Cosmos SDK Docs](./docs/README.md) ## Disambiguation diff --git a/cmd/cosmos-sdk-cli/cmd/init.go b/cmd/cosmos-sdk-cli/cmd/init.go index e9e9cd8a9287..fcf30b9724c2 100644 --- a/cmd/cosmos-sdk-cli/cmd/init.go +++ b/cmd/cosmos-sdk-cli/cmd/init.go @@ -14,7 +14,7 @@ import ( tmversion "github.com/tendermint/tendermint/version" ) -var remoteBasecoinPath = "github.com/cosmos/cosmos-sdk/examples/basecoin" +var remoteBasecoinPath = "github.com/cosmos/cosmos-sdk/docs/examples/basecoin" // Replacer to replace all instances of basecoin/basecli/BasecoinApp to project specific names // Gets initialized when initCmd is executing after getting the project name from user diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 4746b3dd4415..0774208ab446 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -12,105 +12,39 @@ module.exports = { nav: [{ text: "Back to Cosmos", link: "https://cosmos.network" }], sidebar: [ { - title: "Introduction", + title: "Overview", collapsable: false, children: [ - "/introduction/cosmos-hub", - "/introduction/tendermint-cosmos", - "/introduction/tendermint" + "/intro/README", + "/intro/sdk-app-architecture", + "/intro/ocap" ] }, { - title: "Getting Started", + title: "Gaia", collapsable: false, children: [ - "/getting-started/voyager", - "/getting-started/installation", - "/getting-started/join-testnet", - "/getting-started/networks" - ] - }, - { - title: "Cosmos SDK", - collapsable: false, - children: [ - ["/sdk/overview", "Overview"], - ["/sdk/core/intro", "Core"], - "/sdk/core/app1", - "/sdk/core/app2", - "/sdk/core/app3", - "/sdk/core/app4", - "/sdk/core/app5", - // "/sdk/modules", - "/sdk/clients" - ] - }, - // { - // title: "Specifications", - // collapsable: false, - // children: [ - // ["/specs/overview", "Overview"], - // "/specs/governance", - // "/specs/ibc", - // "/specs/staking", - // "/specs/icts", - // ] - // }, - { - title: "SDK by Examples - Simple Governance", - collapsable: false, - children: [ - ["/sdk/sdk-by-examples/simple-governance/intro", "Intro"], - "/sdk/sdk-by-examples/simple-governance/setup-and-design", - "/sdk/sdk-by-examples/simple-governance/app-init", - "/sdk/sdk-by-examples/simple-governance/simple-gov-module", - "/sdk/sdk-by-examples/simple-governance/bridging-it-all", - "/sdk/sdk-by-examples/simple-governance/running-the-application" - ] - }, - { - title: "Light Client", - collapsable: false, - children: [ - "/lite/", - "/lite/getting_started" - ] - }, - { - title: "Lotion JS", - collapsable: false, - children: [ - ["/lotion/overview", "Overview"] - ] - }, - { - title: "Validators", - collapsable: false, - children: [ - ["/validators/overview", "Overview"], - ["/validators/security", "Security"], - ["/validators/validator-setup", "Validator Setup"], - "/validators/validator-faq" + "/gaia/installation", + "/gaia/join-testnet", + "/gaia/networks", + "/gaia/validators/overview", + "/gaia/validators/security", + "/gaia/validators/validator-faq", + "/gaia/validators/validator-setup", + "/gaia/ledger" ] }, { title: "Clients", collapsable: false, children: [ - ["/clients/service-providers", "Service Providers"] - ] - }, - { - title: "Resources", - collapsable: false, - children: [ - // ["/resources/faq" "General"], - "/resources/delegator-faq", - ["/resources/whitepaper", "Whitepaper - English"], - ["/resources/whitepaper-ko", "Whitepaper - 한국어"], - ["/resources/whitepaper-zh-CN", "Whitepaper - 中文"], - ["/resources/whitepaper-pt", "Whitepaper - Português"] - ] + "/clients/README", + "/lite/", // this renders the readme + "/lite/getting_started", + "/lite/specification", + "/clients/cli", + "/clients/service-providers" + ] } ] } diff --git a/docs/DOCS_README.md b/docs/DOCS_README.md index 48a31c2ea929..a27f093b4507 100644 --- a/docs/DOCS_README.md +++ b/docs/DOCS_README.md @@ -1,4 +1,8 @@ -# Docs Build Workflow +## Updating the docs + +If you want to open a PR on the Cosmos SDK to update the documentation, please follow the guidelines in the [`CONTRIBUTING.md`](https://github.com/cosmos/cosmos-sdk/tree/master/CONTRIBUTING.md) + +## Docs Build Workflow The documentation for the Cosmos SDK is hosted at: @@ -15,34 +19,34 @@ Besides, gaia-lite API docs are also provided by gaia-lite. The default API docs https://localhost:1317/swagger-ui/ ``` -## How It Works +### How It Works There is a Jenkins job listening for changes in the `/docs` directory, on both the `master` and `develop` branches. Any updates to files in this directory on those branches will automatically trigger a website deployment. Under the hood, a private website repository has make targets consumed by a standard Jenkins task. -## README +### README The [README.md](./README.md) is also the landing page for the documentation on the website. During the Jenkins build, the current commit is added to the bottom of the README. -## Config.js +### Config.js The [config.js](./.vuepress/config.js) generates the sidebar and Table of Contents on the website docs. Note the use of relative links and the omission of file extensions. Additional features are available to improve the look of the sidebar. -## Links +### Links **NOTE:** Strongly consider the existing links - both within this directory and to the website docs - when moving or deleting files. Relative links should be used nearly everywhere, having discovered and weighed the following: -### Relative +#### Relative Where is the other file, relative to the current one? @@ -50,7 +54,7 @@ Where is the other file, relative to the current one? - confusing / annoying to have things like: `../../../../myfile.md` - requires more updates when files are re-shuffled -### Absolute +#### Absolute Where is the other file, given the root of the repo? @@ -58,12 +62,12 @@ Where is the other file, given the root of the repo? - this is much nicer: `/docs/hereitis/myfile.md` - if you move that file around, the links inside it are preserved (but not to it, of course) -### Full +#### Full The full GitHub URL to a file or directory. Used occasionally when it makes sense to send users to the GitHub. -## Building Locally +### Building Locally To build and serve the documentation locally, run: @@ -94,12 +98,12 @@ python -m SimpleHTTPServer 8080 then navigate to localhost:8080 in your browser. -## Consistency +### Consistency Because the build processes are identical (as is the information contained herein), this file should be kept in sync as much as possible with its [counterpart in the Tendermint Core repo](https://github.com/tendermint/tendermint/blob/develop/docs/DOCS_README.md). -## Update and Build the RPC docs +### Update and Build the RPC docs 1. Execute the following command at the root directory to install the swagger-ui generate tool. ``` diff --git a/docs/README.md b/docs/README.md index 13b831f39318..fbdf89797bef 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,24 +1,38 @@ -# Welcome to the Cosmos Docs! +# Welcome to the SDK Docs! -![cosmonaut reading the cosmos docs in space](./graphics/cosmos-docs.jpg) +Welcome to the SDK docs! -Cosmos is a decentralized network of independent parallel blockchains, each powered by classical BFT consensus algorithms like Tendermint. -The first blockchain in the Cosmos Network is the Cosmos Hub, whose native token is the Atom. Cosmos is a permission-less network, meaning that anybody can build a blockchain on it. +![cosmonaut reading the cosmos docs in space](./cosmos-docs.jpg) -Cosmos can interoperate with multiple other applications and cryptocurrencies. By creating a new zone, you can plug any blockchain system into the Cosmos hub and pass tokens back and forth between those zones, without the need for an intermediary. +## Learn the SDK -## Quick Start +### SDK Intro -- [Getting started with the SDK](./sdk/core/intro.md) -- [SDK Examples](../examples) -- [Join the testnet](./getting-started/join-testnet.md#run-a-full-node) +If you are a newcomer and would like to learn more about the Cosmos SDK, this **[intro](./intro/README.md)** is a good starting place. + +### SDK tutorial + +If you like to learn by doing, you can follow the **[SDK application tutorial](https://github.com/cosmos/sdk-application-tutorial)**. It showcases how to build an SDK-based blockchain from scratch, and teaches you about the basic principles the SDK in the process. + +## Use the SDK + +The following sections contain the information you need if you want to build a fully-functional SDK-based blockchain: + +>*NOTE*: We are currently working on improving the docs. Some info might be missing. If that is the case, try the Cosmos [Forum](https://forum.cosmos.network). Failing that, [open an issue](https://github.com/cosmos/cosmos-sdk/issues/new). + +- [Introduction](./intro/README.md): Contains introductory high-level material on the Cosmos SDK. +- [Gaia](./gaia/README.md): Contains all documentation related to the gaia application (current name for the Cosmos-Hub). +- [Clients](./clients/README.md): Documentation about SDK clients like the SDK Command-Line interface and the SDK Light-client. +- [Specifications](./spec/README.md): Contains SDK and modules specifications. + +If you are reading this on the Cosmos Website, please know that you can find more information on [github](https://github.com/cosmos/cosmos-sdk/tree/develop/docs). Also if you find any issues with the documentation please [*open a Pull Request*](https://github.com/cosmos/cosmos-sdk/compare?expand=1), or at least [*open an Issue*](https://github.com/cosmos/cosmos-sdk/issues/new) to update the docs! + +## Join the public testnet for the Cosmos Hub + +To install the latest version of the `gaia` application and join the public testnet, **click [here](./gaia/README.md#join-the-cosmos-hub-public-testnet)** ## Edit the Documentation See [this file](./DOCS_README.md) for details of the build process and considerations when making changes. - -## Version - -This documentation is built from the following commit: diff --git a/docs/clients/node.md b/docs/_attic/node.md similarity index 100% rename from docs/clients/node.md rename to docs/_attic/node.md diff --git a/docs/sdk/core/app1.md b/docs/_attic/sdk/core/app1.md similarity index 100% rename from docs/sdk/core/app1.md rename to docs/_attic/sdk/core/app1.md diff --git a/docs/sdk/core/app2.md b/docs/_attic/sdk/core/app2.md similarity index 100% rename from docs/sdk/core/app2.md rename to docs/_attic/sdk/core/app2.md diff --git a/docs/sdk/core/app3.md b/docs/_attic/sdk/core/app3.md similarity index 100% rename from docs/sdk/core/app3.md rename to docs/_attic/sdk/core/app3.md diff --git a/docs/sdk/core/app4.md b/docs/_attic/sdk/core/app4.md similarity index 100% rename from docs/sdk/core/app4.md rename to docs/_attic/sdk/core/app4.md diff --git a/docs/sdk/core/app5.md b/docs/_attic/sdk/core/app5.md similarity index 100% rename from docs/sdk/core/app5.md rename to docs/_attic/sdk/core/app5.md diff --git a/docs/sdk/core/examples/app1.go b/docs/_attic/sdk/core/examples/app1.go similarity index 100% rename from docs/sdk/core/examples/app1.go rename to docs/_attic/sdk/core/examples/app1.go diff --git a/docs/sdk/core/examples/app2.go b/docs/_attic/sdk/core/examples/app2.go similarity index 100% rename from docs/sdk/core/examples/app2.go rename to docs/_attic/sdk/core/examples/app2.go diff --git a/docs/sdk/core/examples/app2_test.go b/docs/_attic/sdk/core/examples/app2_test.go similarity index 100% rename from docs/sdk/core/examples/app2_test.go rename to docs/_attic/sdk/core/examples/app2_test.go diff --git a/docs/sdk/core/examples/app3.go b/docs/_attic/sdk/core/examples/app3.go similarity index 100% rename from docs/sdk/core/examples/app3.go rename to docs/_attic/sdk/core/examples/app3.go diff --git a/docs/sdk/core/examples/app4.go b/docs/_attic/sdk/core/examples/app4.go similarity index 100% rename from docs/sdk/core/examples/app4.go rename to docs/_attic/sdk/core/examples/app4.go diff --git a/docs/sdk/core/examples/app4_test.go b/docs/_attic/sdk/core/examples/app4_test.go similarity index 100% rename from docs/sdk/core/examples/app4_test.go rename to docs/_attic/sdk/core/examples/app4_test.go diff --git a/docs/sdk/core/intro.md b/docs/_attic/sdk/core/intro.md similarity index 100% rename from docs/sdk/core/intro.md rename to docs/_attic/sdk/core/intro.md diff --git a/docs/sdk/core/multistore.md b/docs/_attic/sdk/core/multistore.md similarity index 100% rename from docs/sdk/core/multistore.md rename to docs/_attic/sdk/core/multistore.md diff --git a/docs/sdk/sdk-by-examples/intro.md b/docs/_attic/sdk/sdk-by-examples/intro.md similarity index 100% rename from docs/sdk/sdk-by-examples/intro.md rename to docs/_attic/sdk/sdk-by-examples/intro.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/app-init.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/app-init.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/app-init.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/app-init.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/bridging-it-all.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/bridging-it-all.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/bridging-it-all.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/intro.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/intro.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/intro.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/intro.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/running-the-application.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/running-the-application.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/running-the-application.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/running-the-application.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/setup-and-design.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/setup-and-design.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/setup-and-design.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/setup-and-design.md diff --git a/docs/sdk/sdk-by-examples/simple-governance/simple-gov-module.md b/docs/_attic/sdk/sdk-by-examples/simple-governance/simple-gov-module.md similarity index 100% rename from docs/sdk/sdk-by-examples/simple-governance/simple-gov-module.md rename to docs/_attic/sdk/sdk-by-examples/simple-governance/simple-gov-module.md diff --git a/docs/architecture/adr-002-docs-structure.md b/docs/architecture/adr-002-docs-structure.md new file mode 100644 index 000000000000..4d80ad711579 --- /dev/null +++ b/docs/architecture/adr-002-docs-structure.md @@ -0,0 +1,94 @@ +# ADR 002: SDK Documentation Structure + +## Context + +There is a need for a scalable structure of the SDK documentation. Current documentation includes a lot of non-related SDK material, is difficult to maintain and hard to follow as a user. + +Ideally, we would have: +- All docs related to dev frameworks or tools live in their respective github repos (sdk repo would contain sdk docs, hub repo would contain hub docs, lotion repo would contain lotion docs, etc.) +- All other docs (faqs, whitepaper, high-level material about Cosmos) would live on the website. + +## Decision + +Re-structure the `/docs` folder of the SDK github repo as follows: + +``` +docs/ +├── README +├── intro/ +├── gaia/ +│ ├── overview.md +│ ├── install.md +│ ├── join-testnet.md +│ ├── validator-node.md +│ ├── validator-faq.md +│ └── delegator-faq.md +├── reference/ +│ ├── baseapp +│ ├── types +│ ├── store +│ ├── server +│ ├── modules/ +│ │ ├── keeper +│ │ ├── handler +│ │ ├── cli +│ ├── gas +│ └── commands +├── examples/ +│ ├── basecoin/ +│ └── democoin/ +├── clients/ +│ ├── lite/ +│ ├── service-providers +├── spec/ +└── architecture/ +``` + +The files in each sub-folders do not matter and will likely change. What matters is the sectioning: + +- `README`: Landing page of the docs. +- `into`: Introductory material. Goal is to have a short explainer of the SDK and then channel people to the resource they need. The [sdk-tutorial](https://github.com/cosmos/sdk-application-tutorial/) will be highlighted, as well as the `godocs`. +- `gaia`: Contains all docs related to the `gaia` application. Will later be renamed to `cosmos-hub` or `chub` and probably moved to its own repository. +- `reference`: Contains high-level explanations of the abstractions of the SDK. It does not contain specific code implementation and does not need to be updated often. **It is not an API specification of the interfaces**. API spec is the `godoc`. +- `examples`: Contain a couple examples of sdk application like `basecoin` and `democoin`. Developers need to maintain them up-to-date and make sure they compile as the SDK gets upgraded. +- `clients`: Contains specs and info about the various SDK clients. +- `spec`: Contains specs of modules, and others. +- `architecture`: Contains architecture-related docs like the present one. + +Website docs sidebar will only include the following sections: + +- `README` +- `intro` +- `gaia` +- `reference` +- `clients` + +`architecture` and `examples` need not be displayed on the website. As for `modules`, we might need to think about creating a modules manager, but this is out of scope for this document. + +## Status + +Proposed + +## Consequences + +### Positive + +- Much clearer organisation of the SDK docs. +- The `/docs` folder now only contains SDK and gaia related material. Later, it will only contain SDK related material. +- Developers only have to update `/docs` folder when they open a PR (and not `/examples` for example). +- Easier for developers to find what they need to update in the docs thanks to reworked architecture. +- Cleaner vuepress build for website docs. +- Will help build an executable doc (cf https://github.com/cosmos/cosmos-sdk/issues/2611) + +### Neutral + +- We need to move a bunch of deprecated stuff to `/_attic` folder. +- We need to integrate content in `docs/sdk/docs/core` in `reference`. +- We need to move all the content that currently lives in `docs` and does not fit in new structure (like `lotion`, intro material, whitepaper) to the website repository. +- Update `DOCS_README.md` + +## References + +- https://github.com/cosmos/cosmos-sdk/issues/1460 +- https://github.com/cosmos/cosmos-sdk/pull/2695 +- https://github.com/cosmos/cosmos-sdk/issues/2611 \ No newline at end of file diff --git a/docs/architecture/decision-records/README.md b/docs/architecture/decision-records/README.md deleted file mode 100644 index 7c669566df6c..000000000000 --- a/docs/architecture/decision-records/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Architecture Decision Records (ADR) - -This is a location to record all high-level architecture decisions in the cosmos-sdk project. - -You can read more about the ADR concept in this [blog post](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t). - -An ADR should provide: - -- Context on the relevant goals and the current state -- Proposed changes to achieve the goals -- Summary of pros and cons -- References -- Changelog - -Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and -justification for a change in architecture, or for the architecture of something -new. The spec is much more compressed and streamlined summary of everything as -it stands today. - -If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match. - -Note the context/background should be written in the present tense. diff --git a/docs/architecture/decision-records/adr-001-message-counter.md b/docs/architecture/decision-records/adr-001-message-counter.md deleted file mode 100644 index 0e9f25990eed..000000000000 --- a/docs/architecture/decision-records/adr-001-message-counter.md +++ /dev/null @@ -1,54 +0,0 @@ -# ADR 001: Global Message Counter - -## Context - -There is a desire for modules to have a concept of orderings between messages. - -One such example is in staking, we currently use an "intra bond tx counter" and -bond height. -The purpose these two serve is to providing an ordering for validators with equal stake, -for usage in the power-ranking of validators. -We can't use address here, as that would create a bad incentive to grind -addresses that optimized the sort function, which lowers the private key's -security. -Instead we order by whose transaction appeared first, as tracked by bondHeight -and intra bond tx counter. - -This logic however should not be unique to staking. -It is very conceivable that many modules in the future will want to be able to -know the ordering of messages / objects after they were initially created. - -## Decision - -Create a global message counter field of type int64. -Note that with int64's, there is no fear of overflow under normal use, -as it is only getting incremented by one, -and thus has a space of 9 quintillion values to go through. - -This counter must be persisted in state, but can just be read and written on -begin/end block respectively. -This field will get incremented upon every DeliverTx, -regardless if the transaction succeeds or not. -It must also be incremented within the check state for CheckTx. -The global message ordering field should be set within the context -so that modules can access it. - -## Corollary - Intra block ordering -In the event that there is desire to just have an intra block msg counter, -this can easily be derived from the global message counter. -Simply subtract current counter from first global message counter in the block. -Thus the relevant module could easily implement this. - -## Status -Proposed - -## Consequences - -### Positive -* Moves message ordering out of the set of things staking must keep track of -* Abstracts the logic well so other modules can use it - -### Negative -* Another thing to implement prelaunch. (Though this should be easy to implement) - -### Neutral diff --git a/docs/architecture/decision-records/adr-template.md b/docs/architecture/decision-records/adr-template.md deleted file mode 100644 index 6153a9d1ee21..000000000000 --- a/docs/architecture/decision-records/adr-template.md +++ /dev/null @@ -1,32 +0,0 @@ -# ADR {ADR-NUMBER}: {TITLE} - -## Changelog -* {date}: {changelog} - -## Context -> This section contains all the context one needs to understand the current state, and why there is a problem. It should be as succinct as possible and introduce the high level idea behind the solution. - -## Decision -> This section explains all of the details of the proposed solution, including implementation details. -It should also describe affects / corollary items that may need to be changed as a part of this. -If the proposed change will be large, please also indicate a way to do the change to maximize ease of review. -(e.g. the optimal split of things to do between separate PR's) - -## Status -> A decision may be "proposed" if it hasn't been agreed upon yet, or "accepted" once it is agreed upon. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement. - -{Deprecated|Proposed|Accepted} - -## Consequences -> This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones. - -### Positive - -### Negative - -### Neutral - -## References -> Are there any relevant PR comments, issues that led up to this, or articles referrenced for why we made the given design choice? If so link them here! - -* {reference link} diff --git a/docs/clients/README.md b/docs/clients/README.md new file mode 100644 index 000000000000..835b6ee5095b --- /dev/null +++ b/docs/clients/README.md @@ -0,0 +1,18 @@ +# Clients + +This section explains contains information on clients for SDK based blockchain. + +>*NOTE*: This section is a WIP. + +## Light-client + +Light-clients enable users to interact with your application without having to download the entire state history but with a good level of security. + +- [Overview of light clients](./lite/README.md) +- [Starting a light-client server](./lite/getting_started.md) +- [Light-client specification](./lite/specification.md) + +## Other clients + +- [Command-Line interface for SDK-based blockchain](./cli.md) +- [Service provider doc](./service-providers.md) diff --git a/docs/clients/cli.md b/docs/clients/cli.md index dbd234d3721c..fda1ef60b91e 100644 --- a/docs/clients/cli.md +++ b/docs/clients/cli.md @@ -1,8 +1,3 @@ # CLI -See `gaiacli --help` for more details. - -Also see the [testnet -tutorial](https://github.com/cosmos/cosmos-sdk/tree/develop/cmd/gaia/testnets). - -TODO: cleanup the UX and document this properly. +> TODO: Rewrite this section to explain how CLI works for a generic SDK app. diff --git a/docs/lite/getting_started.md b/docs/clients/lite/getting_started.md similarity index 94% rename from docs/lite/getting_started.md rename to docs/clients/lite/getting_started.md index b602bcc47687..15bc8a2794a5 100644 --- a/docs/lite/getting_started.md +++ b/docs/clients/lite/getting_started.md @@ -13,7 +13,7 @@ To start a REST server, we need to specify the following parameters: For example:: ```bash -gaiacli rest-server --chain-id=test \ +gaiacli advanced rest-server --chain-id=test \ --laddr=tcp://localhost:1317 \ --node tcp://localhost:26657 \ --trust-node=false @@ -22,7 +22,7 @@ gaiacli rest-server --chain-id=test \ The server listens on HTTPS by default. You can set the SSL certificate to be used by the server with these additional flags: ```bash -gaiacli rest-server --chain-id=test \ +gaiacli advanced rest-server --chain-id=test \ --laddr=tcp://localhost:1317 \ --node tcp://localhost:26657 \ --trust-node=false \ diff --git a/docs/lite/pics/C2H.png b/docs/clients/lite/pics/C2H.png similarity index 100% rename from docs/lite/pics/C2H.png rename to docs/clients/lite/pics/C2H.png diff --git a/docs/lite/pics/H2C.png b/docs/clients/lite/pics/H2C.png similarity index 100% rename from docs/lite/pics/H2C.png rename to docs/clients/lite/pics/H2C.png diff --git a/docs/lite/pics/MA.png b/docs/clients/lite/pics/MA.png similarity index 100% rename from docs/lite/pics/MA.png rename to docs/clients/lite/pics/MA.png diff --git a/docs/lite/pics/absence1.png b/docs/clients/lite/pics/absence1.png similarity index 100% rename from docs/lite/pics/absence1.png rename to docs/clients/lite/pics/absence1.png diff --git a/docs/lite/pics/absence2.png b/docs/clients/lite/pics/absence2.png similarity index 100% rename from docs/lite/pics/absence2.png rename to docs/clients/lite/pics/absence2.png diff --git a/docs/lite/pics/absence3.png b/docs/clients/lite/pics/absence3.png similarity index 100% rename from docs/lite/pics/absence3.png rename to docs/clients/lite/pics/absence3.png diff --git a/docs/lite/pics/architecture.png b/docs/clients/lite/pics/architecture.png similarity index 100% rename from docs/lite/pics/architecture.png rename to docs/clients/lite/pics/architecture.png diff --git a/docs/lite/pics/changeProcess.png b/docs/clients/lite/pics/changeProcess.png similarity index 100% rename from docs/lite/pics/changeProcess.png rename to docs/clients/lite/pics/changeProcess.png diff --git a/docs/lite/pics/commitValidation.png b/docs/clients/lite/pics/commitValidation.png similarity index 100% rename from docs/lite/pics/commitValidation.png rename to docs/clients/lite/pics/commitValidation.png diff --git a/docs/lite/pics/create-account.png b/docs/clients/lite/pics/create-account.png similarity index 100% rename from docs/lite/pics/create-account.png rename to docs/clients/lite/pics/create-account.png diff --git a/docs/lite/pics/deposit.png b/docs/clients/lite/pics/deposit.png similarity index 100% rename from docs/lite/pics/deposit.png rename to docs/clients/lite/pics/deposit.png diff --git a/docs/lite/pics/existProof.png b/docs/clients/lite/pics/existProof.png similarity index 100% rename from docs/lite/pics/existProof.png rename to docs/clients/lite/pics/existProof.png diff --git a/docs/lite/pics/high-level.png b/docs/clients/lite/pics/high-level.png similarity index 100% rename from docs/lite/pics/high-level.png rename to docs/clients/lite/pics/high-level.png diff --git a/docs/lite/pics/light-client-architecture.png b/docs/clients/lite/pics/light-client-architecture.png similarity index 100% rename from docs/lite/pics/light-client-architecture.png rename to docs/clients/lite/pics/light-client-architecture.png diff --git a/docs/lite/pics/loadbalanceDiagram.png b/docs/clients/lite/pics/loadbalanceDiagram.png similarity index 100% rename from docs/lite/pics/loadbalanceDiagram.png rename to docs/clients/lite/pics/loadbalanceDiagram.png diff --git a/docs/lite/pics/simpleMerkleTree.png b/docs/clients/lite/pics/simpleMerkleTree.png similarity index 100% rename from docs/lite/pics/simpleMerkleTree.png rename to docs/clients/lite/pics/simpleMerkleTree.png diff --git a/docs/lite/pics/substoreProof.png b/docs/clients/lite/pics/substoreProof.png similarity index 100% rename from docs/lite/pics/substoreProof.png rename to docs/clients/lite/pics/substoreProof.png diff --git a/docs/lite/pics/transfer-tokens.png b/docs/clients/lite/pics/transfer-tokens.png similarity index 100% rename from docs/lite/pics/transfer-tokens.png rename to docs/clients/lite/pics/transfer-tokens.png diff --git a/docs/lite/pics/transfer.png b/docs/clients/lite/pics/transfer.png similarity index 100% rename from docs/lite/pics/transfer.png rename to docs/clients/lite/pics/transfer.png diff --git a/docs/lite/pics/trustPropagate.png b/docs/clients/lite/pics/trustPropagate.png similarity index 100% rename from docs/lite/pics/trustPropagate.png rename to docs/clients/lite/pics/trustPropagate.png diff --git a/docs/lite/pics/updateValidatorToHeight.png b/docs/clients/lite/pics/updateValidatorToHeight.png similarity index 100% rename from docs/lite/pics/updateValidatorToHeight.png rename to docs/clients/lite/pics/updateValidatorToHeight.png diff --git a/docs/lite/pics/validatorSetChange.png b/docs/clients/lite/pics/validatorSetChange.png similarity index 100% rename from docs/lite/pics/validatorSetChange.png rename to docs/clients/lite/pics/validatorSetChange.png diff --git a/docs/lite/pics/withdraw.png b/docs/clients/lite/pics/withdraw.png similarity index 100% rename from docs/lite/pics/withdraw.png rename to docs/clients/lite/pics/withdraw.png diff --git a/docs/lite/readme.md b/docs/clients/lite/readme.md similarity index 58% rename from docs/lite/readme.md rename to docs/clients/lite/readme.md index 215bc25f7173..3811f3c3eeab 100644 --- a/docs/lite/readme.md +++ b/docs/clients/lite/readme.md @@ -16,65 +16,61 @@ maintaining any full blockchain nodes. ### What is a lite Client -The LCD is split into two separate components. The first component is generic for any Tendermint +The Cosmos SDK Light Client (Gaia-lite) is split into two separate components. The first component is generic for any Tendermint based application. It handles the security and connectivity aspects of following the header chain and verify proofs from full nodes against locally trusted validator set. Furthermore it exposes exactly the same API as any Tendermint Core node. The second component is specific for the Cosmos -Hub (Gaiad). It works as a query endpoint and exposes the application specific functionality, which +Hub (`gaiad`). It works as a query endpoint and exposes the application specific functionality, which can be arbitrary. All queries against the application state have to go through the query endpoint. The advantage of the query endpoint is that it can verify the proofs that the application returns. ### High-Level Architecture -An application developer that would like to build a third party integration can ship his application -with the LCD for the Cosmos Hub (or any other zone) and only needs to initialise it. Afterwards his -application can interact with the zone as if it was running against a full node. - -![high-level](pics/high-level.png) - -An application developer that wants to build an third party application for the Cosmos Hub (or any -other zone) should build it against it's canonical API. That API is a combination of multiple parts. +An application developer that wants to build a third party client application for the Cosmos Hub (or any +other zone) should build it against its canonical API. That API is a combination of multiple parts. All zones have to expose ICS0 (TendermintAPI). Beyond that any zone is free to choose any combination of module APIs, depending on which modules the state machine uses. The Cosmos Hub will -initially support ICS0 (TendermintAPI), ICS1 (KeyAPI), ICS20 (TokenAPI), ICS21 (StakingAPI) and -ICS22 (GovernanceAPI). +initially support [ICS0](https://cosmos.network/rpc/#/ICS0) (TendermintAPI), [ICS1](https://cosmos.network/rpc/#/ICS1) (KeyAPI), [ICS20](https://cosmos.network/rpc/#/ICS20) (TokenAPI), [ICS21](https://cosmos.network/rpc/#/ICS21) (StakingAPI), +[ICS22](https://cosmos.network/rpc/#/ICS22) (GovernanceAPI) and [ICS23](https://cosmos.network/rpc/#/ICS23) (SlashingAPI). + +![high-level](./pics/high-level.png) -All applications are expected to only run against the LCD. The LCD is the only piece of software +All applications are expected to only run against Gaia-lite. Gaia-lite is the only piece of software that offers stability guarantees around the zone API. ### Comparision A full node of ABCI is different from its lite client in the following ways: -|| Full Node | LCD | Description| +|| Full Node | Gaia-lite | Description| |-| ------------- | ----- | -------------- | -| Execute and verify transactions|Yes|No|Full node will execute and verify all transactions while LCD won't| -| Verify and save blocks|Yes|No|Full node will verify and save all blocks while LCD won't| -| Participate consensus| Yes|No|Only when the full node is a validtor, it will participate consensus. LCD nodes never participate consensus| -| Bandwidth cost|Huge|Little|Full node will receive all blocks. if the bandwidth is limited, it will fall behind the main network. What's more, if it happens to be a validator,it will slow down the consensus process. LCD requires little bandwidth. Only when serving local request, it will cost bandwidth| +| Execute and verify transactions|Yes|No|Full node will execute and verify all transactions while Gaia-lite won't| +| Verify and save blocks|Yes|No|Full node will verify and save all blocks while Gaia-lite won't| +| Participate consensus| Yes|No|Only when the full node is a validtor, it will participate consensus. Lite nodes never participate consensus| +| Bandwidth cost|Huge|Little|Full node will receive all blocks. if the bandwidth is limited, it will fall behind the main network. What's more, if it happens to be a validator,it will slow down the consensus process. Light clients requires little bandwidth. Only when serving local request, it will cost bandwidth| | Computing resource|Huge|Little|Full node will execute all transactions and verify all blocks which require much computing resource| -| Storage resource|Huge|Little|Full node will save all blocks and ABCI states. LCD just saves validator sets and some checkpoints| -| Power consume|Huge|Little|Full nodes have to be deployed on machines which have high performance and will be running all the time. So power consume will be huge. LCD can be deployed on the same machines as users' applications, or on independent machines but with poor performance. Besides, LCD can be shutdown anytime when necessary. So LCD only consume very little power, even mobile devices can meet the power requirement| -| Provide APIs|All cosmos APIs|Modular APIs|Full node supports all cosmos APIs. LCD provides modular APIs according to users' configuration| -| Secuity level| High|High|Full node will verify all transactions and blocks by itself. LCD can't do this, but it can query any data from other full nodes and verify the data independently. So both full node and LCD don't need to trust any third nodes, they all can achieve high security| +| Storage resource|Huge|Little|Full node will save all blocks and ABCI states. Gaia-lite just saves validator sets and some checkpoints| +| Power consume|Huge|Little|Full nodes have to be deployed on machines which have high performance and will be running all the time. So power consume will be huge. Gaia-lite can be deployed on the same machines as users' applications, or on independent machines but with poor performance. Besides, lite clients can be shutdown anytime when necessary. So Gaia-lite only consume very little power, even mobile devices can meet the power requirement| +| Provide APIs|All cosmos APIs|Modular APIs|Full node supports all cosmos APIs. Gaia-lite provides modular APIs according to users' configuration| +| Secuity level| High|High|Full node will verify all transactions and blocks by itself. A light client can't do this, but it can query any data from other full nodes and verify the data independently. So both full nodes and light clients don't need to trust any third nodes, they all can achieve high security| -According to the above table, LCD can meet all users' functionality and security requirements, but +According to the above table, Gaia-lite can meet all users' functionality and security requirements, but only requires little resource on bandwidth, computing, storage and power. ## Achieving Security ### Trusted Validator Set -The base design philosophy of the LCD follows two rules: +The base design philosophy of Gaia-lite follows two rules: 1. **Doesn't trust any blockchain nodes, including validator nodes and other full nodes** 2. **Only trusts the whole validator set** The original trusted validator set should be prepositioned into its trust store, usually this -validator set comes from genesis file. During runtime, if LCD detects a different validator set, +validator set comes from genesis file. During runtime, if Gaia-lite detects a different validator set, it will verify it and save new validated validator set to the trust store. -![validator-set-change](pics/validatorSetChange.png) +![validator-set-change](./pics/validatorSetChange.png) ### Trust Propagation @@ -83,8 +79,8 @@ validator set evolution. Validator set is the foundation of trust, and the trust other blockchain data, such as block and transaction. The propagate architecture is shown as follows: -![change-process](pics/trustPropagate.png) +![change-process](./pics/trustPropagate.png) -In general, by trusted validator set, LCD can verify each block commit which contains all pre-commit +In general, by trusted validator set, a light client can verify each block commit which contains all pre-commit data and block header data. Then the block hash, data hash and appHash are trusted. Based on this and merkle proof, all transactions data and ABCI states can be verified too. diff --git a/docs/lite/specification.md b/docs/clients/lite/specification.md similarity index 95% rename from docs/lite/specification.md rename to docs/clients/lite/specification.md index 4feac508ccd8..032f840a59bc 100644 --- a/docs/lite/specification.md +++ b/docs/clients/lite/specification.md @@ -12,7 +12,7 @@ we need to extract name, height and store root hash from these substores to buil Merkle leaf nodes, then calculate hash from leaf nodes to root. The root hash of the simple Merkle tree is the AppHash which will be included in block header. -![Simple Merkle Tree](pics/simpleMerkleTree.png) +![Simple Merkle Tree](./pics/simpleMerkleTree.png) As we have discussed in [LCD trust-propagation](https://github.com/irisnet/cosmos-sdk/tree/bianjie/lcd_spec/docs/spec/lcd#trust-propagation), the AppHash can be verified by checking voting power against a trusted validator set. Here we just @@ -65,7 +65,7 @@ type KeyExistsProof struct { The data structure of exist proof is shown as above. The process to build and verify existance proof is shown as follows: -![Exist Proof](pics/existProof.png) +![Exist Proof](./pics/existProof.png) Steps to build proof: @@ -92,12 +92,12 @@ the postition of the target key in the whole key set of this IAVL tree. As shown out the left key and the right key. If we can demonstrate that both left key and right key definitely exist, and they are adjacent nodes. Thus the target key definitely doesn't exist. -![Absence Proof1](pics/absence1.png) +![Absence Proof1](./pics/absence1.png) If the target key is larger than the right most leaf node or less than the left most key, then the target key definitely doesn't exist. -![Absence Proof2](pics/absence2.png)![Absence Proof3](pics/absence3.png) +![Absence Proof2](./pics/absence2.png)![Absence Proof3](./pics/absence3.png) ```go type proofLeafNode struct { @@ -147,7 +147,7 @@ in commitID equals to proof RootHash. If not, the proof is invalid. Then sort th commitInfo array by the hash of substore name. Finally, build the simple Merkle tree with all substore commitInfo array and verify if the Merkle root hash equal to appHash. -![substore proof](pics/substoreProof.png) +![substore proof](./pics/substoreProof.png) ```go func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { @@ -187,7 +187,7 @@ Above sections refer appHash frequently. But where does the trusted appHash come appHash exist in block header, so next we need to verify blocks header at specific height against LCD trusted validator set. The validation flow is shown as follows: -![commit verification](pics/commitValidation.png) +![commit verification](./pics/commitValidation.png) When the trusted validator set doesn't match the block header, we need to try to update our validator set to the height of this block. LCD have a rule that each validator set change should not @@ -198,7 +198,7 @@ validator set update be accomplished. For instance: -![Update validator set to height](pics/updateValidatorToHeight.png) +![Update validator set to height](./pics/updateValidatorToHeight.png) * Update to 10000, tooMuchChangeErr * Update to 5050, tooMuchChangeErr diff --git a/docs/clients/rest.md b/docs/clients/rest.md deleted file mode 100644 index b48ec7d8fc98..000000000000 --- a/docs/clients/rest.md +++ /dev/null @@ -1,6 +0,0 @@ -# REST - -See `gaiacli rest-server --help` for more. - -Also see the -[work in progress API specification](https://github.com/cosmos/cosmos-sdk/pull/1314) diff --git a/docs/clients/service-providers.md b/docs/clients/service-providers.md index 11fe2c779243..b7e6d500cb01 100644 --- a/docs/clients/service-providers.md +++ b/docs/clients/service-providers.md @@ -83,7 +83,7 @@ It will display all the available commands. For each command, you can use the `- ## Setting up the Rest Server -The Rest Server acts as an intermediary between the front-end and the full-node. You don't need to run the Rest Server on the same machine as the full-node. If you intend to run the Rest Server on another machine, you need to go through the [Installation and configuration](#installation-and-configuration) again on this machine. +The Rest Server acts as an intermediary between the front-end and the full-node. You don't need to run the Rest Server on the same machine as the full-node. To start the Rest server: @@ -109,4 +109,6 @@ The Rest API documents all the available endpoints that you can use to interract The API is divided into ICS standards for each category of endpoints. For example, the [ICS20](https://cosmos.network/rpc/#/ICS20/) describes the API to interact with tokens. -To give more flexibility to implementers, we have separated the different steps that are involved in the process of sending transactions. You will be able to generate unsigned transactions (example with [coin transfer](https://cosmos.network/rpc/#/ICS20/post_bank_accounts__address__transfers)), [sign](https://cosmos.network/rpc/#/ICS20/post_tx_sign) and [broadcast](https://cosmos.network/rpc/#/ICS20/post_tx_broadcast) them with different API endpoints. This allows service providers to use their own signing mechanism for instance. +To give more flexibility to implementers, we have included the ability to generate unsigned transactions, [sign](https://cosmos.network/rpc/#/ICS20/post_tx_sign) and [broadcast](https://cosmos.network/rpc/#/ICS20/post_tx_broadcast) them with different API endpoints. This allows service providers to use their own signing mechanism for instance. + +In order to generate an unsigned transaction (example with [coin transfer](https://cosmos.network/rpc/#/ICS20/post_bank_accounts__address__transfers)), you need to use the flag `?generate_only`. diff --git a/docs/graphics/cosmos-docs.jpg b/docs/cosmos-docs.jpg similarity index 100% rename from docs/graphics/cosmos-docs.jpg rename to docs/cosmos-docs.jpg diff --git a/examples/README.md b/docs/examples/README.md similarity index 100% rename from examples/README.md rename to docs/examples/README.md diff --git a/examples/basecoin/app/app.go b/docs/examples/basecoin/app/app.go similarity index 98% rename from examples/basecoin/app/app.go rename to docs/examples/basecoin/app/app.go index 286afd003e26..9515feaadc52 100644 --- a/examples/basecoin/app/app.go +++ b/docs/examples/basecoin/app/app.go @@ -6,7 +6,7 @@ import ( bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" + "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" diff --git a/examples/basecoin/app/app_test.go b/docs/examples/basecoin/app/app_test.go similarity index 97% rename from examples/basecoin/app/app_test.go rename to docs/examples/basecoin/app/app_test.go index c49d5d4768dd..64bc6a86e778 100644 --- a/examples/basecoin/app/app_test.go +++ b/docs/examples/basecoin/app/app_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" + "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/stretchr/testify/require" diff --git a/examples/basecoin/cli_test/cli_test.go b/docs/examples/basecoin/cli_test/cli_test.go similarity index 100% rename from examples/basecoin/cli_test/cli_test.go rename to docs/examples/basecoin/cli_test/cli_test.go diff --git a/examples/basecoin/cmd/basecli/main.go b/docs/examples/basecoin/cmd/basecli/main.go similarity index 95% rename from examples/basecoin/cmd/basecli/main.go rename to docs/examples/basecoin/cmd/basecli/main.go index 4ebd1bef8476..3a16c8a97bbd 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/docs/examples/basecoin/cmd/basecli/main.go @@ -7,8 +7,8 @@ import ( _ "github.com/cosmos/cosmos-sdk/client/lcd/statik" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/examples/basecoin/app" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" + "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/app" + "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types" "github.com/cosmos/cosmos-sdk/version" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" diff --git a/examples/basecoin/cmd/basecoind/main.go b/docs/examples/basecoin/cmd/basecoind/main.go similarity index 98% rename from examples/basecoin/cmd/basecoind/main.go rename to docs/examples/basecoin/cmd/basecoind/main.go index f07fbd3ff2b6..0e265d1897d4 100644 --- a/examples/basecoin/cmd/basecoind/main.go +++ b/docs/examples/basecoin/cmd/basecoind/main.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/basecoin/app" + "github.com/cosmos/cosmos-sdk/docs/examples/basecoin/app" "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/examples/basecoin/types/account.go b/docs/examples/basecoin/types/account.go similarity index 100% rename from examples/basecoin/types/account.go rename to docs/examples/basecoin/types/account.go diff --git a/examples/democoin/app/app.go b/docs/examples/democoin/app/app.go similarity index 95% rename from examples/democoin/app/app.go rename to docs/examples/democoin/app/app.go index e8ddd066d7cd..bc618e3606ae 100644 --- a/examples/democoin/app/app.go +++ b/docs/examples/democoin/app/app.go @@ -17,11 +17,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/examples/democoin/types" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/sketchy" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/types" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/simplestake" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/sketchy" ) const ( diff --git a/examples/democoin/app/app_test.go b/docs/examples/democoin/app/app_test.go similarity index 94% rename from examples/democoin/app/app_test.go rename to docs/examples/democoin/app/app_test.go index 5b3be00e1205..93cef936c7fc 100644 --- a/examples/democoin/app/app_test.go +++ b/docs/examples/democoin/app/app_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/types" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/types" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/stretchr/testify/require" diff --git a/examples/democoin/cli_test/cli_test.go b/docs/examples/democoin/cli_test/cli_test.go similarity index 100% rename from examples/democoin/cli_test/cli_test.go rename to docs/examples/democoin/cli_test/cli_test.go diff --git a/examples/democoin/cmd/democli/main.go b/docs/examples/democoin/cmd/democli/main.go similarity index 86% rename from examples/democoin/cmd/democli/main.go rename to docs/examples/democoin/cmd/democli/main.go index 4121fa30b5e3..adb6169c9ee5 100644 --- a/examples/democoin/cmd/democli/main.go +++ b/docs/examples/democoin/cmd/democli/main.go @@ -16,11 +16,11 @@ import ( bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" - "github.com/cosmos/cosmos-sdk/examples/democoin/app" - "github.com/cosmos/cosmos-sdk/examples/democoin/types" - coolcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool/client/cli" - powcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow/client/cli" - simplestakingcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake/client/cli" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/app" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/types" + coolcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool/client/cli" + powcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow/client/cli" + simplestakingcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/simplestake/client/cli" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/examples/democoin/cmd/democoind/main.go b/docs/examples/democoin/cmd/democoind/main.go similarity index 98% rename from examples/democoin/cmd/democoind/main.go rename to docs/examples/democoin/cmd/democoind/main.go index d095b4c79066..36ea11cc31b2 100644 --- a/examples/democoin/cmd/democoind/main.go +++ b/docs/examples/democoin/cmd/democoind/main.go @@ -21,7 +21,7 @@ import ( gaiaInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/app" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/app" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/examples/democoin/mock/validator.go b/docs/examples/democoin/mock/validator.go similarity index 100% rename from examples/democoin/mock/validator.go rename to docs/examples/democoin/mock/validator.go diff --git a/examples/democoin/types/account.go b/docs/examples/democoin/types/account.go similarity index 94% rename from examples/democoin/types/account.go rename to docs/examples/democoin/types/account.go index ad57c944d385..341f6cfc834c 100644 --- a/examples/democoin/types/account.go +++ b/docs/examples/democoin/types/account.go @@ -5,8 +5,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow" ) var _ auth.Account = (*AppAccount)(nil) diff --git a/examples/democoin/x/assoc/validator_set.go b/docs/examples/democoin/x/assoc/validator_set.go similarity index 100% rename from examples/democoin/x/assoc/validator_set.go rename to docs/examples/democoin/x/assoc/validator_set.go diff --git a/examples/democoin/x/assoc/validator_set_test.go b/docs/examples/democoin/x/assoc/validator_set_test.go similarity index 97% rename from examples/democoin/x/assoc/validator_set_test.go rename to docs/examples/democoin/x/assoc/validator_set_test.go index 9fc6526f8d3e..66f03c840324 100644 --- a/examples/democoin/x/assoc/validator_set_test.go +++ b/docs/examples/democoin/x/assoc/validator_set_test.go @@ -10,7 +10,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/mock" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/mock" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/examples/democoin/x/cool/app_test.go b/docs/examples/democoin/x/cool/app_test.go similarity index 100% rename from examples/democoin/x/cool/app_test.go rename to docs/examples/democoin/x/cool/app_test.go diff --git a/examples/democoin/x/cool/client/cli/tx.go b/docs/examples/democoin/x/cool/client/cli/tx.go similarity index 96% rename from examples/democoin/x/cool/client/cli/tx.go rename to docs/examples/democoin/x/cool/client/cli/tx.go index c30743f03d9e..a21685a249f3 100644 --- a/examples/democoin/x/cool/client/cli/tx.go +++ b/docs/examples/democoin/x/cool/client/cli/tx.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool" sdk "github.com/cosmos/cosmos-sdk/types" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" diff --git a/examples/democoin/x/cool/codec.go b/docs/examples/democoin/x/cool/codec.go similarity index 100% rename from examples/democoin/x/cool/codec.go rename to docs/examples/democoin/x/cool/codec.go diff --git a/examples/democoin/x/cool/errors.go b/docs/examples/democoin/x/cool/errors.go similarity index 100% rename from examples/democoin/x/cool/errors.go rename to docs/examples/democoin/x/cool/errors.go diff --git a/examples/democoin/x/cool/handler.go b/docs/examples/democoin/x/cool/handler.go similarity index 100% rename from examples/democoin/x/cool/handler.go rename to docs/examples/democoin/x/cool/handler.go diff --git a/examples/democoin/x/cool/keeper.go b/docs/examples/democoin/x/cool/keeper.go similarity index 100% rename from examples/democoin/x/cool/keeper.go rename to docs/examples/democoin/x/cool/keeper.go diff --git a/examples/democoin/x/cool/keeper_test.go b/docs/examples/democoin/x/cool/keeper_test.go similarity index 100% rename from examples/democoin/x/cool/keeper_test.go rename to docs/examples/democoin/x/cool/keeper_test.go diff --git a/examples/democoin/x/cool/types.go b/docs/examples/democoin/x/cool/types.go similarity index 100% rename from examples/democoin/x/cool/types.go rename to docs/examples/democoin/x/cool/types.go diff --git a/examples/democoin/x/oracle/README.md b/docs/examples/democoin/x/oracle/README.md similarity index 100% rename from examples/democoin/x/oracle/README.md rename to docs/examples/democoin/x/oracle/README.md diff --git a/examples/democoin/x/oracle/errors.go b/docs/examples/democoin/x/oracle/errors.go similarity index 100% rename from examples/democoin/x/oracle/errors.go rename to docs/examples/democoin/x/oracle/errors.go diff --git a/examples/democoin/x/oracle/handler.go b/docs/examples/democoin/x/oracle/handler.go similarity index 100% rename from examples/democoin/x/oracle/handler.go rename to docs/examples/democoin/x/oracle/handler.go diff --git a/examples/democoin/x/oracle/keeper.go b/docs/examples/democoin/x/oracle/keeper.go similarity index 100% rename from examples/democoin/x/oracle/keeper.go rename to docs/examples/democoin/x/oracle/keeper.go diff --git a/examples/democoin/x/oracle/keeper_keys.go b/docs/examples/democoin/x/oracle/keeper_keys.go similarity index 100% rename from examples/democoin/x/oracle/keeper_keys.go rename to docs/examples/democoin/x/oracle/keeper_keys.go diff --git a/examples/democoin/x/oracle/oracle_test.go b/docs/examples/democoin/x/oracle/oracle_test.go similarity index 98% rename from examples/democoin/x/oracle/oracle_test.go rename to docs/examples/democoin/x/oracle/oracle_test.go index 1284f75b6dec..b8b613e318d3 100644 --- a/examples/democoin/x/oracle/oracle_test.go +++ b/docs/examples/democoin/x/oracle/oracle_test.go @@ -10,7 +10,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/mock" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/mock" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/examples/democoin/x/oracle/types.go b/docs/examples/democoin/x/oracle/types.go similarity index 100% rename from examples/democoin/x/oracle/types.go rename to docs/examples/democoin/x/oracle/types.go diff --git a/examples/democoin/x/pow/app_test.go b/docs/examples/democoin/x/pow/app_test.go similarity index 100% rename from examples/democoin/x/pow/app_test.go rename to docs/examples/democoin/x/pow/app_test.go diff --git a/examples/democoin/x/pow/client/cli/tx.go b/docs/examples/democoin/x/pow/client/cli/tx.go similarity index 95% rename from examples/democoin/x/pow/client/cli/tx.go rename to docs/examples/democoin/x/pow/client/cli/tx.go index 22de7e09855c..548aa9910746 100644 --- a/examples/democoin/x/pow/client/cli/tx.go +++ b/docs/examples/democoin/x/pow/client/cli/tx.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow" sdk "github.com/cosmos/cosmos-sdk/types" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" diff --git a/examples/democoin/x/pow/codec.go b/docs/examples/democoin/x/pow/codec.go similarity index 100% rename from examples/democoin/x/pow/codec.go rename to docs/examples/democoin/x/pow/codec.go diff --git a/examples/democoin/x/pow/errors.go b/docs/examples/democoin/x/pow/errors.go similarity index 100% rename from examples/democoin/x/pow/errors.go rename to docs/examples/democoin/x/pow/errors.go diff --git a/examples/democoin/x/pow/handler.go b/docs/examples/democoin/x/pow/handler.go similarity index 100% rename from examples/democoin/x/pow/handler.go rename to docs/examples/democoin/x/pow/handler.go diff --git a/examples/democoin/x/pow/handler_test.go b/docs/examples/democoin/x/pow/handler_test.go similarity index 100% rename from examples/democoin/x/pow/handler_test.go rename to docs/examples/democoin/x/pow/handler_test.go diff --git a/examples/democoin/x/pow/keeper.go b/docs/examples/democoin/x/pow/keeper.go similarity index 100% rename from examples/democoin/x/pow/keeper.go rename to docs/examples/democoin/x/pow/keeper.go diff --git a/examples/democoin/x/pow/keeper_test.go b/docs/examples/democoin/x/pow/keeper_test.go similarity index 100% rename from examples/democoin/x/pow/keeper_test.go rename to docs/examples/democoin/x/pow/keeper_test.go diff --git a/examples/democoin/x/pow/mine.go b/docs/examples/democoin/x/pow/mine.go similarity index 100% rename from examples/democoin/x/pow/mine.go rename to docs/examples/democoin/x/pow/mine.go diff --git a/examples/democoin/x/pow/types.go b/docs/examples/democoin/x/pow/types.go similarity index 100% rename from examples/democoin/x/pow/types.go rename to docs/examples/democoin/x/pow/types.go diff --git a/examples/democoin/x/pow/types_test.go b/docs/examples/democoin/x/pow/types_test.go similarity index 100% rename from examples/democoin/x/pow/types_test.go rename to docs/examples/democoin/x/pow/types_test.go diff --git a/examples/democoin/x/simplestake/client/cli/commands.go b/docs/examples/democoin/x/simplestake/client/cli/commands.go similarity index 97% rename from examples/democoin/x/simplestake/client/cli/commands.go rename to docs/examples/democoin/x/simplestake/client/cli/commands.go index b5c0730efa1d..3fe9c20c4ac7 100644 --- a/examples/democoin/x/simplestake/client/cli/commands.go +++ b/docs/examples/democoin/x/simplestake/client/cli/commands.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake" + "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/simplestake" sdk "github.com/cosmos/cosmos-sdk/types" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" diff --git a/examples/democoin/x/simplestake/codec.go b/docs/examples/democoin/x/simplestake/codec.go similarity index 100% rename from examples/democoin/x/simplestake/codec.go rename to docs/examples/democoin/x/simplestake/codec.go diff --git a/examples/democoin/x/simplestake/errors.go b/docs/examples/democoin/x/simplestake/errors.go similarity index 100% rename from examples/democoin/x/simplestake/errors.go rename to docs/examples/democoin/x/simplestake/errors.go diff --git a/examples/democoin/x/simplestake/handler.go b/docs/examples/democoin/x/simplestake/handler.go similarity index 100% rename from examples/democoin/x/simplestake/handler.go rename to docs/examples/democoin/x/simplestake/handler.go diff --git a/examples/democoin/x/simplestake/keeper.go b/docs/examples/democoin/x/simplestake/keeper.go similarity index 100% rename from examples/democoin/x/simplestake/keeper.go rename to docs/examples/democoin/x/simplestake/keeper.go diff --git a/examples/democoin/x/simplestake/keeper_test.go b/docs/examples/democoin/x/simplestake/keeper_test.go similarity index 100% rename from examples/democoin/x/simplestake/keeper_test.go rename to docs/examples/democoin/x/simplestake/keeper_test.go diff --git a/examples/democoin/x/simplestake/msgs.go b/docs/examples/democoin/x/simplestake/msgs.go similarity index 100% rename from examples/democoin/x/simplestake/msgs.go rename to docs/examples/democoin/x/simplestake/msgs.go diff --git a/examples/democoin/x/simplestake/msgs_test.go b/docs/examples/democoin/x/simplestake/msgs_test.go similarity index 100% rename from examples/democoin/x/simplestake/msgs_test.go rename to docs/examples/democoin/x/simplestake/msgs_test.go diff --git a/examples/democoin/x/simplestake/types.go b/docs/examples/democoin/x/simplestake/types.go similarity index 100% rename from examples/democoin/x/simplestake/types.go rename to docs/examples/democoin/x/simplestake/types.go diff --git a/examples/democoin/x/sketchy/handler.go b/docs/examples/democoin/x/sketchy/handler.go similarity index 100% rename from examples/democoin/x/sketchy/handler.go rename to docs/examples/democoin/x/sketchy/handler.go diff --git a/examples/kvstore/kvstore b/docs/examples/kvstore/kvstore similarity index 100% rename from examples/kvstore/kvstore rename to docs/examples/kvstore/kvstore diff --git a/examples/kvstore/main.go b/docs/examples/kvstore/main.go similarity index 100% rename from examples/kvstore/main.go rename to docs/examples/kvstore/main.go diff --git a/examples/kvstore/tx.go b/docs/examples/kvstore/tx.go similarity index 100% rename from examples/kvstore/tx.go rename to docs/examples/kvstore/tx.go diff --git a/docs/gaia/README.md b/docs/gaia/README.md new file mode 100644 index 000000000000..9ecf3da2384d --- /dev/null +++ b/docs/gaia/README.md @@ -0,0 +1,19 @@ +# Gaia Documentation + +Welcome to the `Gaia` docs. `Gaia` is the current name of the Cosmos SDK application for the Cosmos Hub. + +## Join the Cosmos Hub public testnet + +- [Install the `gaia` application](./installation.md) +- [Join the current testnet](./join-testnet.md) +- [Upgrade to a validator node](./validators/validator-setup.md) + +## Setup your own `gaia` testnet + +- [Setup your own `gaia` testnet](./networks.md) + +## Additional resources + +- [Intro to validators](./validators/overview.md) +- [Validator FAQ](./validators/validator-faq.md) +- [Validator security considerations](./validators/security.md) diff --git a/docs/sdk/clients.md b/docs/gaia/gaiacli.md similarity index 88% rename from docs/sdk/clients.md rename to docs/gaia/gaiacli.md index 3c0ca5c50110..5749e1ca776c 100644 --- a/docs/sdk/clients.md +++ b/docs/gaia/gaiacli.md @@ -1,15 +1,7 @@ -# Clients - -::: tip Note -🚧 We are actively working on documentation for SDK clients. -::: +# Gaia client ## Gaia CLI -::: tip Note -🚧 We are actively working on improving documentation for Gaiacli and Gaiad. -::: - ::: tip Note If you receive this error message: @@ -208,13 +200,13 @@ On the upcoming mainnet, you can delegate `atom` to a validator. These [delegato You can query the list of all validators of a specific chain: ```bash -gaiacli query validators +gaiacli query stake validators ``` If you want to get the information of a single validator you can check it with: ```bash -gaiacli query validator +gaiacli query stake validator ``` #### Bond Tokens @@ -222,7 +214,7 @@ gaiacli query validator On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond tokens to a testnet validator (*i.e.* delegate): ```bash -gaiacli tx delegate \ +gaiacli tx stake delegate \ --amount=10steak \ --validator= \ --from= \ @@ -248,7 +240,7 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau Once submitted a delegation to a validator, you can see it's information by using the following command: ```bash -gaiacli query delegation \ +gaiacli query stake delegation \ --address-delegator= \ --validator= ``` @@ -256,7 +248,7 @@ gaiacli query delegation \ Or if you want to check all your current delegations with disctinct validators: ```bash -gaiacli query delegations +gaiacli query stake delegations ``` You can also get previous delegation(s) status by adding the `--height` flag. @@ -266,7 +258,7 @@ You can also get previous delegation(s) status by adding the `--height` flag. If for any reason the validator misbehaves, or you just want to unbond a certain amount of tokens, use this following command. You can unbond a specific `shares-amount` (eg:`12.1`\) or a `shares-fraction` (eg:`0.25`) with the corresponding flags. ```bash -gaiacli tx unbond begin \ +gaiacli tx stake unbond \ --validator= \ --shares-fraction=0.5 \ --from= \ @@ -280,7 +272,7 @@ The unbonding will be automatically completed when the unbonding period has pass Once you begin an unbonding-delegation, you can see it's information by using the following command: ```bash -gaiacli query unbonding-delegation \ +gaiacli query stake unbonding-delegation \ --address-delegator= \ --validator= \ ``` @@ -288,13 +280,13 @@ gaiacli query unbonding-delegation \ Or if you want to check all your current unbonding-delegations with disctinct validators: ```bash -gaiacli query unbonding-delegations +gaiacli query stake unbonding-delegations ``` Additionally, as you can get all the unbonding-delegations from a particular validator: ```bash - gaiacli query unbonding-delegations-from + gaiacli query stake unbonding-delegations-from ``` To get previous unbonding-delegation(s) status on past blocks, try adding the `--height` flag. @@ -304,7 +296,7 @@ To get previous unbonding-delegation(s) status on past blocks, try adding the `- A redelegation is a type delegation that allows you to bond illiquid tokens from one validator to another: ```bash -gaiacli tx redelegate begin \ +gaiacli tx stake redelegate \ --addr-validator-source= \ --addr-validator-dest= \ --shares-fraction=50 \ @@ -321,7 +313,7 @@ The redelegation will be automatically completed when the unbonding period has p Once you begin an redelegation, you can see it's information by using the following command: ```bash -gaiacli query redelegation \ +gaiacli query stake redelegation \ --address-delegator= \ --addr-validator-source= \ --addr-validator-dest= \ @@ -330,17 +322,48 @@ gaiacli query redelegation \ Or if you want to check all your current unbonding-delegations with disctinct validators: ```bash -gaiacli query redelegations +gaiacli query stake redelegations ``` Additionally, as you can get all the outgoing redelegations from a particular validator: ```bash - gaiacli query redelegations-from + gaiacli query stake redelegations-from ``` To get previous redelegation(s) status on past blocks, try adding the `--height` flag. +#### Query Parameters + +Parameters define high level settings for staking. You can get the current values by using: + +```bash +gaiacli query stake parameters +``` + +With the above command you will get the values for: + +- Unbonding time +- Maximum numbers of validators +- Coin denomination for staking + +All these values will be subject to updates though a `governance` process by `ParameterChange` proposals. + +#### Query Pool + +A staking `Pool` defines the dynamic parameters of the current state. You can query them with the following command: + +```bash +gaiacli query stake pool +``` + +With the `pool` command you will get the values for: + +- Loose and bonded tokens +- Token supply +- Current anual inflation and the block in which the last inflation was processed +- Last recorded bonded shares + ##### Query Delegations To Validator You can also query all of the delegations to a particular validator: @@ -361,7 +384,7 @@ Some considerations about the voting process: - Voters can choose between options `Yes`, `No`, `NoWithVeto` and `Abstain` At the end of the voting period, a proposal is accepted if `(YesVotes/(YesVotes+NoVotes+NoWithVetoVotes))>1/2` and `(NoWithVetoVotes/(YesVotes+NoVotes+NoWithVetoVotes))<1/3`. It is rejected otherwise -For more information about the governance process and how it works, please check out the Governance module [specification](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/governance). +For more information about the governance process and how it works, please check out the Governance module [specification](./../spec/governance). #### Create a Governance proposal @@ -372,7 +395,7 @@ In order to create a governance proposal, you must submit an initial deposit alo - `type`: Type of proposal. Must be of value _Text_ (types _SoftwareUpgrade_ and _ParameterChange_ not supported yet). ```bash -gaiacli tx submit-proposal \ +gaiacli tx gov submit-proposal \ --title= \ --description=<description> \ --type=<Text/ParameterChange/SoftwareUpgrade> \ @@ -386,14 +409,13 @@ gaiacli tx submit-proposal \ Once created, you can now query information of the proposal: ```bash -gaiacli query proposal \ - --proposal-id=<proposal_id> +gaiacli query gov proposal --proposal-id=<proposal_id> ``` Or query all available proposals: ```bash -gaiacli query proposals +gaiacli query gov proposals ``` You can also query proposals filtered by `voter` or `depositer` by using the corresponding flags. @@ -403,7 +425,7 @@ You can also query proposals filtered by `voter` or `depositer` by using the cor In order for a proposal to be broadcasted to the network, the amount deposited must be above a `minDeposit` value (default: `10 steak`). If the proposal you previously created didn't meet this requirement, you can still increase the total amount deposited to activate it. Once the minimum deposit is reached, the proposal enters voting period: ```bash -gaiacli tx deposit \ +gaiacli tx gov deposit \ --proposal-id=<proposal_id> \ --deposit=<200steak> \ --from=<name> \ @@ -412,62 +434,54 @@ gaiacli tx deposit \ > _NOTE_: Proposals that don't meet this requirement will be deleted after `MaxDepositPeriod` is reached. +##### Query deposits + +Once a new proposal is created, you can query all the deposits submitted to it: + +```bash +gaiacli query gov deposits --proposal-id=<proposal_id> +``` + +You can also query a deposit submitted by a specific address: + +```bash +gaiacli query gov deposit \ + --proposal-id=<proposal_id> \ + --depositer=<account_cosmos> +``` + #### Vote on a proposal After a proposal's deposit reaches the `MinDeposit` value, the voting period opens. Bonded `Atom` holders can then cast vote on it: ```bash -gaiacli tx vote \ +gaiacli tx gov vote \ --proposal-id=<proposal_id> \ --option=<Yes/No/NoWithVeto/Abstain> \ --from=<name> \ --chain-id=<chain_id> ``` -##### Query vote +##### Query votes Check the vote with the option you just submitted: ```bash -gaiacli query vote \ +gaiacli query gov vote \ --proposal-id=<proposal_id> \ --voter=<account_cosmos> ``` -#### Query Parameters - -You can get the current parameters that define high level settings for staking: +You can also get all the previous votes submitted to the proposal with: -``` -gaiacli query parameters +```bash +gaiacli query gov votes --proposal-id=<proposal_id> ``` -With the above command you will get the values for: +#### Query proposal tally results -- Unbonding time -- Maximum numbers of validators -- Coin denomination for staking +To check the current tally of a given proposal you can use the `tally` command: -All this values can be updated though a `governance` process by submitting a parameter change `proposal`. - -#### Query Pool - -A staking `Pool` defines the dynamic parameters of the current state. You can query them with the following command: - -``` -gaiacli query pool +```bash +gaiacli query gov tally --proposal-id=<proposal_id> ``` - -With the `pool` command you will get the values for: - -- Loose and bonded tokens -- Token supply -- Current anual inflation and the block in which the last inflation was processed -- Last recorded bonded shares - - -## Gaia-Lite - -::: tip Note -🚧 We are actively working on documentation for Gaia-lite. -::: diff --git a/docs/getting-started/installation.md b/docs/gaia/installation.md similarity index 51% rename from docs/getting-started/installation.md rename to docs/gaia/installation.md index 66ccae4b85e8..c4b78b13cbc9 100644 --- a/docs/getting-started/installation.md +++ b/docs/gaia/installation.md @@ -1,6 +1,6 @@ -# Install the SDK +# Install Gaia -This guide will explain how to install the [Cosmos SDK](/sdk/overview.md) onto your system. With the SDK installed on a server, you can participate in the latest testnet as either a [Full Node](./join-testnet.md#run-a-full-node) or a [Validator](/validators/validator-setup.md). +This guide will explain how to install the `gaiad` and `gaiacli` entrypoints onto your system. With these installed on a server, you can participate in the latest testnet as either a [Full Node](./join-testnet.md#run-a-full-node) or a [Validator](./validators/validator-setup.md). ## Install Go @@ -14,17 +14,13 @@ echo "export PATH=$PATH:$GOBIN" >> ~/.bash_profile ``` ::: tip -**Go 1.10+** is required for the Cosmos SDK. +**Go 1.11+** is required for the Cosmos SDK. ::: ## Install Cosmos SDK -Next, let's install the testnet's version of the Cosmos SDK. -You can find information about the latest testnet and the right -version of the Cosmos-SDK for it in the [testnets -repo](https://github.com/cosmos/testnets#testnet-status). -Here we'll use the `master` branch, which contains the latest stable release. -If necessary, make sure you `git checkout` the correct +Next, let's install the latest version of Gaia. Here we'll use the `master` branch, which contains the latest stable release. +If necessary, make sure you `git checkout` the correct [released version](https://github.com/cosmos/cosmos-sdk/releases). ```bash @@ -35,6 +31,8 @@ cd cosmos-sdk && git checkout master make get_tools && make get_vendor_deps && make install ``` +> *NOTE*: If you have issues at this step, please check that you have the latest stable version of GO installed. + That will install the `gaiad` and `gaiacli` binaries. Verify that everything is OK: ```bash @@ -44,4 +42,4 @@ $ gaiacli version ## Run a Full Node -With Cosmos SDK installed, you can run [a full node on the latest testnet](full-node.md). +With the binaries installed, you can run [a full node on the latest testnet](./join-testnet.md). diff --git a/docs/getting-started/join-testnet.md b/docs/gaia/join-testnet.md similarity index 71% rename from docs/getting-started/join-testnet.md rename to docs/gaia/join-testnet.md index ce070c4fe967..560bbcf6e77f 100644 --- a/docs/getting-started/join-testnet.md +++ b/docs/gaia/join-testnet.md @@ -1,21 +1,23 @@ # Join the Testnet ::: tip Current Testnet -See the [testnet repo](https://github.com/cosmos/testnets) for +See the [testnet repo](https://github.com/cosmos/testnets) for information on the latest testnet, including the correct version of the Cosmos-SDK to use and details about the genesis file. ::: -Please ensure you have the [Cosmos SDK](/getting-started/installation.md) installed. If you ran a full node on a previous testnet, please skip to [Upgrading From Previous Testnet](#upgrading-from-previous-testnet). +**Please ensure you have the [gaia binaries](./installation.md) installed.** + +If you ran a full node on a previous testnet, please skip to [Upgrading From Previous Testnet](#upgrading-from-previous-testnet). ## Setting Up a New Node -These instructions are for setting up a brand new full node from scratch. +These instructions are for setting up a brand new full node from scratch. First, initialize the node and create the necessary config files: ```bash -gaiad init --skip-genesis --name <your_custom_name> +gaiad init ``` ::: warning Note @@ -75,10 +77,14 @@ git fetch --all && git checkout master make update_tools && make get_vendor_deps && make install ``` +::: tip +*NOTE*: If you have issues at this step, please check that you have the latest stable version of GO installed. +::: + Note we use `master` here since it contains the latest stable release. -See the [testnet repo](https://github.com/cosmos/testnets) -for details on which version is needed for which testnet, -and the [SDK release page](https://github.com/cosmos/cosmos-sdk/releases) +See the [testnet repo](https://github.com/cosmos/testnets) +for details on which version is needed for which testnet, +and the [SDK release page](https://github.com/cosmos/cosmos-sdk/releases) for details on each release. Your full node has been cleanly upgraded! @@ -94,20 +100,16 @@ mkdir -p $HOME/.gaiad/config curl https://raw.githubusercontent.com/cosmos/testnets/master/latest/genesis.json > $HOME/.gaiad/config/genesis.json ``` -Note we use the `latest` directory in the [testnets repo](https://github.com/cosmos/testnets) -which contains details for the latest testnet. If you are connecting to a different testnet, ensure you -get the right files. +Note we use the `latest` directory in the [testnets repo](https://github.com/cosmos/testnets) +which contains details for the latest testnet. If you are connecting to a different testnet, ensure you get the right files. ### Add Seed Nodes -Your node needs to know how to find peers. You'll need to add healthy seed nodes to `$HOME/.gaiad/config/config.toml`. Here are some seed nodes you can use: +Your node needs to know how to find peers. You'll need to add healthy seed nodes to `$HOME/.gaiad/config/config.toml`. The `testnets` repo contains links to the seed nodes for each testnet. If you are looking to join the running testnet please [check the repository for details](https://github.com/cosmos/testnets) on which nodes to use. -```toml -# Comma separated list of seed nodes to connect to -seeds = "718145d422a823fd2a4e1e36e91b92bb0c4ddf8e@gaia-testnet.coinculture.net:26656,5922bf29b48a18c2300b85cc53f424fce23927ab@67.207.73.206:26656,7c8b8fd03577cd4817f5be1f03d506f879df98d8@gaia-7000-seed1.interblock.io:26656,a28737ff02391a6e00a1d3b79befd57e68e8264c@gaia-7000-seed2.interblock.io:26656,987ffd26640cd03d08ed7e53b24dfaa7956e612d@gaia-7000-seed3.interblock.io:26656" -``` +If those seeds aren't working, you can find more seeds and persistent peers on the [Cosmos Explorer](https://explorer.cosmos.network/nodes). Open the the `Full Nodes` pane and select nodes that do not have private (`10.x.x.x`) or [local IP addresses](https://en.wikipedia.org/wiki/Private_network). The `Persistent Peer` field contains the connection string. For best results use 4-6. -If those seeds aren't working, you can find more seeds and persistent peers on the [Cosmos Explorer](https://explorecosmos.network/nodes). Open the the `Full Nodes` pane and select nodes that do not have private (`10.x.x.x`) or [local IP addresses](https://en.wikipedia.org/wiki/Private_network). The `Persistent Peer` field contains the connection string. For best results use 4-6. +You can also ask for peers on the [Validators Riot Room](https://riot.im/app/#/room/#cosmos-validators:matrix.org) For more information on seeds and peers, you can [read this](https://github.com/tendermint/tendermint/blob/develop/docs/using-tendermint.md#peers). @@ -130,4 +132,4 @@ View the status of the network with the [Cosmos Explorer](https://explorecosmos. ## Upgrade to Validator Node -You now have an active full node. What's the next step? You can upgrade your full node to become a Cosmos Validator. The top 100 validators have the ability to propose new blocks to the Cosmos Hub. Continue onto [the Validator Setup](../validators/validator-setup.md). +You now have an active full node. What's the next step? You can upgrade your full node to become a Cosmos Validator. The top 100 validators have the ability to propose new blocks to the Cosmos Hub. Continue onto [the Validator Setup](./validators/validator-setup.md). diff --git a/docs/clients/keys.md b/docs/gaia/keys.md similarity index 100% rename from docs/clients/keys.md rename to docs/gaia/keys.md diff --git a/docs/clients/ledger.md b/docs/gaia/ledger.md similarity index 100% rename from docs/clients/ledger.md rename to docs/gaia/ledger.md diff --git a/docs/getting-started/networks.md b/docs/gaia/networks.md similarity index 89% rename from docs/getting-started/networks.md rename to docs/gaia/networks.md index 67f0dab5aa45..3bc08c94b329 100644 --- a/docs/getting-started/networks.md +++ b/docs/gaia/networks.md @@ -56,8 +56,9 @@ make build-linux localnet-stop localnet-start ### Configuration -The `make localnet-start` creates files for a 4-node testnet in `./build` by calling the `gaiad testnet` command. -This outputs a handful of files in the `./build` directory: +The `make localnet-start` creates files for a 4-node testnet in `./build` by +calling the `gaiad testnet` command. This outputs a handful of files in the +`./build` directory: ```tree -L 2 build/ build/ @@ -103,12 +104,29 @@ Each `./build/nodeN` directory is mounted to the `/gaiad` directory in each cont ### Logging -Logs are saved under each `./build/nodeN/gaiad/gaia.log`. Watch them stream in with, for example: +Logs are saved under each `./build/nodeN/gaiad/gaia.log`. You can also watch logs +directly via Docker, for example: ``` -tail -f build/node0/gaiad/gaia.log +docker logs -f gaiadnode0 ``` +### Keys & Accounts + +To interact with `gaiacli` and start querying state or creating txs, you use the +`gaiacli` directory of any given node as your `home`, for example: + +```shell +gaiacli keys list --home ./build/node0/gaiacli +``` + +Now that accounts exists, you may create new accounts and send those accounts +funds! + +::: tip +**Note**: Each node's seed is located at `./build/nodeN/gaiacli/key_seed.json`. +::: + ### Special binaries If you have multiple binaries with different names, you can specify which one to run with the BINARY environment variable. The path of the binary is relative to the attached volume. For example: diff --git a/docs/validators/overview.md b/docs/gaia/validators/overview.md similarity index 100% rename from docs/validators/overview.md rename to docs/gaia/validators/overview.md diff --git a/docs/validators/security.md b/docs/gaia/validators/security.md similarity index 100% rename from docs/validators/security.md rename to docs/gaia/validators/security.md diff --git a/docs/validators/validator-faq.md b/docs/gaia/validators/validator-faq.md similarity index 100% rename from docs/validators/validator-faq.md rename to docs/gaia/validators/validator-faq.md diff --git a/docs/validators/validator-setup.md b/docs/gaia/validators/validator-setup.md similarity index 85% rename from docs/validators/validator-setup.md rename to docs/gaia/validators/validator-setup.md index d07697136fbd..61872bcf9cd6 100644 --- a/docs/validators/validator-setup.md +++ b/docs/gaia/validators/validator-setup.md @@ -1,14 +1,14 @@ # Validator Setup -::: warning Current Testnet -The current testnet is `gaia-8000`. +::: tip +Information on how to join the current testnet (`genesis.json` file and seeds) is held [in our `testnet` repo](https://github.com/cosmos/testnets/tree/master/latest). Please check there if you are looking to join our latest testnet. ::: Before setting up your validator node, make sure you've already gone through the [Full Node Setup](/docs/getting-started/full-node.md) guide. ## Running a Validator Node -[Validators](/validators/overview.md) are responsible for committing new blocks to the blockchain through voting. A validator's stake is slashed if they become unavailable, double sign a transaction, or don't cast their votes. Please read about [Sentry Node Architecture](/validators/validator-faq.md#how-can-validators-protect-themselves-from-denial-of-service-attacks) to protect your node from DDOS attacks and to ensure high-availability. +[Validators](/validators/overview.md) are responsible for committing new blocks to the blockchain through voting. A validator's stake is slashed if they become unavailable or sign blocks at the same height. Please read about [Sentry Node Architecture](/validators/validator-faq.md#how-can-validators-protect-themselves-from-denial-of-service-attacks) to protect your node from DDOS attacks and to ensure high-availability. ::: danger Warning If you want to become a validator for the Hub's `mainnet`, you should [research security](/validators/security.md). @@ -22,14 +22,14 @@ Your `cosmosvalconspub` can be used to create a new validator by staking tokens. gaiad tendermint show-validator ``` -Next, craft your `gaiacli tx create-validator` command: +Next, craft your `gaiacli tx stake create-validator` command: ::: warning Note Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://faucetcosmos.network/)! ::: ```bash -gaiacli tx create-validator \ +gaiacli tx stake create-validator \ --amount=5steak \ --pubkey=$(gaiad tendermint show-validator) \ --moniker="choose a moniker" \ @@ -44,6 +44,10 @@ __Note__: When specifying commission parameters, the `commission-max-change-rate is used to measure % _point_ change over the `commission-rate`. E.g. 1% to 2% is a 100% rate increase, but only 1 percentage point. +::: tip +Use `gaiacli tx stake create-validator -h` to get a list of all the available flags. +::: + ### Edit Validator Description You can edit your validator's public description. This info is to identify your validator, and will be relied on by delegators to decide which validators to stake to. Make sure to provide input for every flag below, otherwise the field will default to empty (`--moniker` defaults to the machine name). @@ -51,7 +55,7 @@ You can edit your validator's public description. This info is to identify your The `--identity` can be used as to verify identity with systems like Keybase or UPort. When using with Keybase `--identity` should be populated with a 16-digit string that is generated with a [keybase.io](https://keybase.io) account. It's a cryptographically secure method of verifying your identity across multiple online networks. The Keybase API allows us to retrieve your Keybase avatar. This is how you can add a logo to your validator profile. ```bash -gaiacli tx edit-validator +gaiacli tx stake edit-validator --moniker="choose a moniker" \ --website="https://cosmos.network" \ --identity=6A0D65E29A4CBC8E \ @@ -73,7 +77,7 @@ __Note__: The `commission-rate` value must adhere to the following invariants: View the validator's information with this command: ```bash -gaiacli query validator <account_cosmos> +gaiacli query stake validator <account_cosmos> ``` ### Track Validator Signing Information @@ -81,7 +85,7 @@ gaiacli query validator <account_cosmos> In order to keep track of a validator's signatures in the past you can do so by using the `signing-info` command: ```bash -gaiacli query signing-info <validator-pubkey>\ +gaiacli query slashing signing-info <validator-pubkey>\ --chain-id=<chain_id> ``` @@ -90,7 +94,7 @@ gaiacli query signing-info <validator-pubkey>\ When a validator is "jailed" for downtime, you must submit an `Unjail` transaction from the operator account in order to be able to get block proposer rewards again (depends on the zone fee distribution). ```bash -gaiacli tx unjail \ +gaiacli tx slashing unjail \ --from=<key_name> \ --chain-id=<chain_id> ``` @@ -124,7 +128,7 @@ gaiad start Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmos>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`. ```bash -gaiacli tx unjail <cosmos> --chain-id=<chain_id> --from=<from> +gaiacli tx slashing unjail <cosmos> --chain-id=<chain_id> --from=<from> ``` ::: danger Warning diff --git a/docs/getting-started/voyager.md b/docs/getting-started/voyager.md deleted file mode 100644 index 7fa17f24cc1a..000000000000 --- a/docs/getting-started/voyager.md +++ /dev/null @@ -1,9 +0,0 @@ -# Download Voyager - -Voyager is the official desktop app for the Cosmos Network. It provides an intuitive interface for managing accounts, creating transactions, delegation, and governance. - -Download the [latest Voyager release](https://github.com/cosmos/voyager/releases). - -### Delving Deeper - -If you're familar with the CLI, you should consider running a full node or validator for the latest Cosmos testnet. [Learn more](/getting-started/installation.md). diff --git a/docs/graphics/cosmos-sdk-image.png b/docs/graphics/cosmos-sdk-image.png deleted file mode 100644 index ab9a4abc68c829a7bbdbfdfbc652670f633b3fe6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190395 zcmeFZRa6{7*YDjp!3iNa3=$wX1lJ+By9FnBa37pNkU)^&!6CT2ySux)yZf0u&wFz& zzl-mzb=Ep}Gt;%Zs&-X(?fUJ1O^Bkr1Ud>K3IG7;Qj(&|0Duhr2oE450sssw5HbP% z2IHtK@fj!?A>Ic7Fd!u=tm+1Hq>Ge{$8m$1qPtL0mF@Z$FaJ9z?;R?r+dDPatbPNc zSG}Z<*_i6?A}|OMQ)pIEI`V~uRnA7GkUVwX_gWXSjT<t(7`#ecwKcsZ5*(yrK5cID zyp*}1j_!{sh@D-3Cj!8N(?uy18$@RaV-aD&U<m*Y@J0rw!&Cagq{DLw7GS`$0Bc+T zyfh0eJ|JzknRNjER|M|=<{|^{&5#dficj<1wQH;{x-d;akxuYGhXKWm&j@iz+Mg6X z`rr@|1Hg8lxnYp0JOSEnXlXoxp$%W(b`V=a2Dd*ll>^W>SlBBaOBbs?cV|#$yQ=4M zw&qtA_p8Gftcpx!3FN8dGSTbuRvyNw6{>%|s{J-A?{YLZp0|MD?g##YB{>ANnXQ5H z(70WLr93bGj>=guhY)h0%o5psTSMSD>p}M$lFwxtOAjX#-`y4S;xOUgBxzOZq)tA1 zB&_jjLH7e;o%w-_kbGJA1k;`sQu(txRqZN#Ic(<_kc=&(Sgh6J0Xi&XGCxfWV0$1I z)p=&O>^w1TLM2yrsvn(*V|(7O6dxW|1R23X9OMEA*3<J+uQWYYG+e7}m9_|dZ<g2B zV!@6a^HHUzmLJ{^%!?g74S-W<3UWO*jz(eB$KCWIza1|?82Ad6v2Y_1U@e3}oN!?3 z<z02NDpZmqOCFvu8<P#J0*%r*`%fD?xYMO+@%FMC24DtKxSg#n@xUJ`kE5u?`mN;J z=g-QiXvfmEY>95Nbtapzi;Iy9&V0Nx_K$JhHT?3t3$=Xyat|9MG9+{my&Sqx<?($q z8m$HH8tY368IHplTjOO9J@Z5bf+jTF$;MN!4sZLxl!7A7N$Kf<L&Z9VRN+rq$<G!5 zxAOs25*y@uMPRmctm!in8XGA(T_Wt;Ngm{2A?12XMtxp24}A)W(qG9m>QRT#;_nJo zN~069T`5{nC#8|%X@nDZ>&-}w<8^seXFu-F_a}x$zLj?{^3KXxo{ys3LDw;AvBF{g zd1<xM6zhD#8ytO2KbjQ~+av`N4+&d^6`jB58BtG3yRfhe=KY%$u8Q;`@|P^*AZV^Z zSIB<^vfbdw+dr6+<`&Z9?5L-Oq~Iu+nsdll`_f<CM7ztyv><uYmy&k%w%H<7&mEgW zh&g&PSmESJ=Veo&Wo-W2bl6DJ_Duj}cn^py2^aQFp`|srZ@e|vc5^-S@wh$WSWnQ+ zulPvfLUGXWa>K>7PyKq;v&!>lgpc~w&=Dqe=RUcl!GV;i6XNz~*RjD<05ajdrd#jX zz>q1ck*BDa+xoDeJ>V(tRI$6(E^@SQ_F7V@?=>ySwDaKpjNUp8iDydO_(F{lMnD7{ znA2}7As*~8YFAH(rgJ;rMR!;!z`>HC1?QWMR?eq-UZ!JZdl??KY(~`X(Fr}&+4=ZK zzu?fw(`s?rEM@*J3@+3tRf*Cazc_H^<cEm`S6iy7ZM|CvtX};)#@&8w&~;Ddxo08p zu!ZxLyMHnkks#NvC%S{3#mowzB^j@DC|BV!AM3*jsNz$MxurV#&SS~Emf|YpVkkx~ z(;R5_$GfPhGI`#s>>Ek*!@HG1N3GfK7-4#RQ5xQj8$!=kzja;82M7BAEHMe>340p( zJN9ft|2-KcYOKsWkE9vK>$l$bg^dBf*>JW~Si^+drGiuh$yt2b-ztEgwjLIpUR<oT zv-|2lGK<mf1cadh>IqdAi&5hR0?*UqEBCHAebu=mmbfcky)P?~TQ?`mUq6%_3U)6E z(e96x7b*qiH4)Fxl~T9TM6>;Qj|6kT?#+uayRI75_;OXoI2egqS~FZbko>gWC?02y zS~}YLs^!*b!196p_l*~z{we*bsil|`e=H4uE5*Zwq*ZdnYnSmiYp=`c!0emSmW!|` z`$v+mnz+Y0zBbDvY~~JI$&QEzRP#0+pp*zilg5dt9C^p>?auj0h2>H_8VuOxM~tsR zPh~T)1XMIGU?z6QhamSUi}Q#}q-F;qH-SJjQUk&{H}5fr3C6S=7_ge~%KdhD2Lvfu z<~BR~Dlv9)#cNlNRBll1=t*@gD<aG=O(7vWzS;QPv&M1PC7YzlW?;xj-t(|^6aV?V zjc+u};z!DC{v`ixhtM2jYh8F~Qps=<7i;!pES7aiOiK4m(Vt?x;X~@3+`$~s_TTIG zZI(A_53$b!*IQCQPR}L*Rx|bW&5ZGQz3w}GEI@RAB&9J#s+W6S#78}))nS`1j(1P9 zvg~^_5wSXt@U`M@dh4f!n`yOk`LEfxEstqam3prlQM(^58uqPbpUkUhH+WyBCQG?5 zNco*KOC!vKR8ojza}vpm;e6GWQK}>y-YpHq9dZ?!u|H0()>vyh^Gt)ss<a#hMhATu zzx=`TMnrGv!#Bnt<2)s8d`t}@R&zZa@BJNgnp0_f7TLaRu;85(5Lqf<b3AEVXJdJP zF>)${Mmn{s%E+8@6w-Ub+Ryvp;sRw=)N3!wEJai9egkAM5DcNPh6B6QJTKa-pR|&A zPv*$8A;N8J!U-3u7i-Oy2po%AU)GWGK1RTzbG9~IV;)8LFg&p?+ieyvKzw_xoX^^a z6q>DY7mXK=n>9j0NJ3tH2jiT5H2Ox(wkitPip=RXO2#XXQa5q@V{Pag)F3wdp?L33 z_8bS9FBrd6$;whwq}ITsf2r;e*ptsY3(wl9)V|u(gXwoZa>|ij!u`c7^g}`LrH#D~ z%i8sYR6Hf^dkUlHj_bjbdabBC4E8IHi+6e6Fwst^)Z*QY9IDENRB7zVJJVlhxs7CM zQ7Yy-G_5%-w8);3b9FYU6tg7zKXyr7bkpQhP`Fa-Cy6mjs?Y(Of<eA8ORTa(yG$E< z5Qx`#51X<SOG|m9X;K9-UdZ!K5hYEQR?*6=SUH<6%j5M!==1B|mc!ED`-o*Zr231W zGET9pOwTKS8w{g6IIy^QxiMEoY?Zet+PC$e8!wHRN{KWcYvW&rvr0;AY(7b1*Ge%& zw66DF>fk1Tax~F_fTU&68q)0b;jBezPuvXB_fTe1L*;f|FN%@G=jxB6az+t5*umtD z${%KmJ#3GEM0YN9tYNUyGupp&W|MtOTUm}ZQC^u;SjpW@@p#FmPR){tuwa(J738db zY!8K01?iz>qHAg4b~8{i4G@XqVKcdoCiLps;Z+3R*g>@JYV=q0j-HZjhZoS@r=(Na zAf(I@gFVlG;%5Dx>l(HY&<IrT0^j?&Now0SU(ePy_C)jEj%P{CNsxt4n><|eMNF5d z(1@j)dXh?t%Q`kJSBwAB5oomEG%eD)RDY<2ZAlfJm+y+H^?Kw~S4>}tw>7$oToV$f zkAnM>YwhxI%!R8UFRxa!(b$p8Sm2piZM~XyTs7~zZ49@}j7e;CGgKE=fYW^4b9vNs ziIPT|cR}WUChyXDt?{LVz;0Rnn!G`pdG~bwQubyX>2*tLds<%aBNm*I6%x=9m|7j` zx9SthUdZjd^Fii)#c4bq;}Dh{nuFQxCm^y#DXVm<Rkg}`@qLZeK1DgQ#(5qm0;3jt z$aKE$WLf(trs@f|p7U5B$$4V42Bh;Yl47~R#W>CTDKO)BP-=2MR^zopvN0q$VeGKm zsRyj=|M+2*eU>Gx*I1~Cp{ci6CmV%`%{WibzuwWb-1$(QNC7RF7872tU;qhsVX%$N z%sndNcdbaSBU~Zog5fByho%8hhw9ld|MkdcW)t}CE*UMQ%N`eC?KYDbaQ9g{M3W== z?W#CI>EcA1>lqakzq>QAeb?}Vh~NzH<0i*C)CORGmcC48{H7GwEBV^XS4tAu<oGrM zr!~)G3F)+Kvo~Tff9A5zyCkU;fg6PmKeGWr@g2fjEEe*}1Q=g!Mpu6MU5y6kbPorV zCdUhYh|ue(&$)JSB_3m&{W6_a$>wkDc-9sz@u>(HU&?@Qzp;X!SPk%RFDTNRCY8)c z1ecmdlgyhgL)qTN^9haXd9If_u_7q>q*Xp9T}TQ!zc5!_!f~gCz`OxPvcOZ20Ryr0 zWV}>U_c^kueFL$~rK_!GCT2vp=P@*{BaRQ(HC4hKERjz;azs_5(bJRH6O6F87__z# z!}l<82;^|cU08m5NWK*#%pP~`KR6f8!oA1Ee(){2eVK6`=GfUCc4(m!_}arR(i&fl z6w5T`3)aC7_5`@SmtL|HL2YMRiLD8plfq6vD|Ga|Uu;r_CMhsCz@UC)(HHzPO?Wup zIqYt&w7siZDaX}rFj25-NlPDPPs&xO$xnx1IKRK-iaE;Lyk9dp|L8@Y6Jd}ETD{#) zxqL2vHIZr6wHko#4nk^{xgxf=r>FO0cKm9JUG^uUXnqyeHI`X7VuZcWD$?L>hlpE@ zOdf=BTHRk{i_VDDxbTLp+O4&Dw`NAd!TMoIPJIQh+%FHcCC86p-}|^+Ixp~e>xRv` z^SCF!j%A1(O)3bk8E?mqz!Ddcy#MUyG#L$3yE|9-&WOwx1$S)14}63KG_;l~e+arh znN;W%IT~^Sl!B=BR?6|1o&ulC9K?PikM0uKT;mAEqc`AS!2uFvvrd#)_Y?+WDCneY zvZqg1d&4rje;q6^Vf)7xU7S|PPRn8>%;3-1&)ufwc<aIro?r(g09bno&<q@KsyQ`o ze)($_x_qJPZb6;#iI?8l{UPfUY@ByvU%JQi@O`&1=txeXDGW3#6NqUTOJ{<l1T$|G z2HsMDc{1wd6RMxRf{VjUwadCiv(B)&E{KgQI$m%!TJ_SXiZtstj~3SU?H8}8ef4d( zIyu@uYHNq%e7jRrw(P_EHNuBwQb$=y+B?a5st<KObW}*W%K)eG)h~Cha<nyP3rj!x z17bZf6V>JXxdVYtmN1Bs)OVJwe(pYh0hhi&A<q8$--&(ZmkX`5JBywjpO_tpHwGg) zgwz}>9Zs_08ySH!FAzHz;FTS|J$0WitA^zCZE*S3RT~6Rn^%YXp`FyWOXgRF2Ivh% z^9jW>YK*Lge?C}y*Cjvd{Ig2XEUmM@r1Sz6{HY~1GwuCSrN(+cM+xqaw!8yP7t7|0 z!G@>4LgTS}6XVIG@M*x{`Xl4_zn0T<C6N}(IVt6J60k-zwaQ?Ae!B?Y+-AMjR6!}c zb+|;0`?5PsGQrHowW;>IG`wXU)2VE(FF*5nt3Fgxz@_NJNdJ+tAOdQv=8rTv9ujuK z2vivEw+J+hw@7N6UG&MQ&f0ws3-y}MhJ>_oQy8Dh(<eb|*E5ne?M%ycT9}Pi0;6(B zshnOl$G~T1>H0S|0}fe8{Oc5vJz{MglcvQ(yD8gyQIzToyeT#aU2uGLp$dts7JS!n zOpHs<vpLotGbOqQBSPBSxu3d)*P1Sa@F|jQX771E>ElzC?$8G*q}eCtl?t2b{Ep|l zi2H@gfcNO;WlWHXRQ=<yhXWthf*43f-~N<KLbHr=*8ctSJiLF>>Dgw!HWkTNE{XFe z-PIxz1-tb^vh(rGWL<Uo*H*KUyMeAk=`r#Q=qAiYChiiGc#bCev)rY;>*c7e*{RQ& zR$fCh?WRjG+ujoeVdAe`X8;thQN6(AYEJMQ1((h|$qzB1&vAEX4C7YkTPA|sP%^7p zzR~a>wXl}~%afB23+2YR^rnf3<b{5r^2jxWz|E<`=*w%oo@dN>8vb{uHkvf|#OIxw zBvI$M^C(It*?v@Im!E7{u#}NAFl_@1`6|>E-p@#Xcw>LMu79s*5b}wqqjw-YzRneR zH8R_U!)q0{36O)CDp##6mJYZ(A-KeUT$Cv-tgyDg6naQLgjus?{(HihUcrhy_c?iH zs0tIHV@_W)_A5^mFM19urTI2G6Y-NuC3!XU(qBX_k(}C%r$XAECA|r{!8W-*<YJrK zQ#G2-9nJdkloc+vdbmk;%#NlcdO~!Gqz~7IF2v|rRG|1q85Ude5ikgfTFN+b>*ha5 zSN8`P-xkaui{7)DOtF}kzAanQxmE#`QhPN#Tf@fFbh)=SlKfpR<ROr2z9h|~CRm}$ za}mrX!--Rx^;{jHZEz2PUzGsjJGl@e#J|Ge)O@7WRgu@Ggh@jXbk(B%liMp5A3u_o z+4jB6RiQ;pp56EY<xZdd!`!#*3N^CJDx!oV4hk+=cs4db5y8c3mC#fGP1h6DSFDs0 z`%za_AXnJ;ot+j0#2SMXCdzsiB{h}U)fz<BpklE<>O)|4qwZz;_|!hL%c#7YySDu` zRk~9+49zc-^sN@QWj9UL<0fsVfa@!(So2(aH#h6UeU82~3@iE5RReu&T%Fgt#0Ocp zu!B#Fp?Hg{7k0XyENd1G9jI92eX{&t;Q%$R0)i-~RiD?dPWB{wiC!_}0}WrCna1fA zojGHPd)uVq?vA$VNzVs_Dj6qKT|(}IB|^dCNI=1t7?RB!zMj235*~-J^E!FSOCO~f z)?qc)pM188>t+jR-$NxwD^Vhp9NSUi*vTW$VSEn=Opxw9I~X`k4m@SJv%CYzOqRQ( z$E}{)>qf<Xn>>{W2^>Lg-p49w$;5fm{MPAJ(}QaQX3u_%B*cA!S=Q9mdmK>sMOeL5 z=Dw35Z*v_SbrEhJv12-te4tet4Q}9V9l)qp8BYypKyS#?6sB)S&Li_R1F(3Xq6OOw zuWxi?sBvpY6g2Zq7id`nPK+tALbU-5l4j#d=Wpzx_H-KhVw*Ma^`;Ixm_}U2GNiEO zgaGo3O0Ilh3$?-aiwXn@vtFn*;w}Z2w-x7eUjz<pIT66kt>i>y-(x#dl&v?FtThRV z@+(!EBc7wB1z<UmyIcTJQocwEKV+iE^Hxh=fu6r0REFJVLg!TvP(Z4mC=qvh0U>|p zR6*`C#U4WeT7)H>!+m4JevSw!)49W_v_5?9J_rd6KYhc*(u?Ld$B*a~Dl_KiJCNac zv{$Yf=^IW4FVNS6;5X+1uqifeA`l>dck<S2vBH}GgF=w0Y=AY;WjMYuXsuyM2LiEi zYlnmX{T*zC1YnfSv33%pp~xp2EV^24cCVqp|NH<OLI!lHV<W-Im#WYx@KFrD96fyP z4Y#C0Io_hEgY|ps4~9BLwHUhPV@Ha}8-PVerb74AJcW}aOen*HeuhB<q`tAvp~8O_ z1>nHJ2A^@UBnhD?_4kYs^m;%rfar_W9zX|*WQT%Qs^V?~W-MfEs1f=1H)>#z1+oDk z`6aYn4}?VlHTn#XQ{W4pz-j{`tKR!JgF&KDqX1-TRTyY2;|l|_U_|ur0|!Hmkg;X+ zU}2?1pmk1sLA!y*A=qsI7Da+00{rhlXq|tn@sAK-$tj>lqAVFG{|6fS55?KhiF!d> z;0yka<%<-V-t#>l46^#yg<rH+Fn;j=x*+@uLB$U|_pb{?N_%jyZ$3l2@SPAf2iC9b zUl%wt$B^LP20*(2&+%Rs0oD)-szFww8JNga$WXVvv1CX<f$tE98qEcNCc~1%g1YVP zlqL%<a=<UBQ5p6RK~N;<pRe=E4WN9K2x??ViQ)wY3IFr8;@5Un5EduYs6+hS!@q_? zef@vDq2T#4+#WIgX}W36?15O_r0BHPQ0Qx=i$e(C4{Q%kpF;zj4`(o^NT&;DBexXF z8MQfO*s1)$=bu62aNsd{+trwC{8^uasgE_z^oVdCO_52W@Nap5v+zWwHknvDLNsV3 z5mREMgn<=I>?ev2?4R7xUDc!GBdhND#<9b{Wd+XU@!l=L>|(I0%BEh`W8dPea~guq z{7H>BzJrg*;4Z@7zhhashxG35r@MDnFz1m(BEfoN1s?-o68fW&Za$&bn>|Pk*^shv z-^f9I{YNJ(U+@xk@HT+u(yK9iLnBXY7E4#ZO0zZ<iA!(%L(qUHHpCNz_0De&9WZqD z#=uIuhPW?GF+<p=zNy{>SyIKo_)Q{rSpvbCmwBc><<}_}VtTdbv<K@oR%b9U%+S{b z&?lO!RcBX%SHypAnkh&J=jiCDYOGMTGo0kM5uZ31_iME?=VE)X-_%`twn&M8#?xq= zP098B{PQkjN~;H6gt$YtyU7OY`VC_!<Kg9&3Ug%;nb!zg8k@J%HSNu8@2ge+Wzy;| z!&iu7k%^$m+`OImVheQLxBbZ<pRZf{RXUZ#Z!k)Jq8KGvB36Q(%Vc5Sj?z}mg?gXh z7RWq#vS~Y>%TFTW)aTzXTKyWaV(ru<@p6&;l9fY7{hEdH1dTP&NY#GqNsK@vPn=S! zODNhTcE*AhZ8eV>cE);sG?}#84xt$Wx#-v+wR#I=jiFMd8j2u&41GR(_QAh#;PEEm z+~Cy}XAsG!%IONj0F+!YYHx2jET_V%AarU4@AAD%o)*aT3ncb??`LWBcZ@fso&Gd` z%=0cwzS)kSWH1w*IPb=r{7<b4O?j6guh`2U?f8=KXkXhOZEH<78}fA2<|)OWr_x&= zE;glgo86tK_v!AnDt8Djni#TwC%pZ{3;e~2hC{-r&~0=f@(IEunF-aec7SY|sumMI z2`=?ZzHF*IONwdH%%-@NK8-VrMaA5y&Cc!SB1^*CP}XV<tyG$&B{+qxx^+&+@#_dN zkN#E~T;taXye!e>(2lt9l#egfZNxifi@n@P9+?BMu8$N_QaTz>oAO;BpzP$&!ur^H zC$Cp~$31V#Wm3XtSy8Q3>3OY&Y<VGNJ(3ZcmpMrCuDxC%{qCj%#p>Al>`y6^<gI#) zs0_8Fj$y6%@D@#~#U3?xD+C6%!>Pl+yD{_{RqSzIgxaXs{!NCPrY2r!feGT!_(gP@ zpo?Gyb4AB{G<6CAO0kU-3G1tkm1*}ma?L(64;1mH<B_O0k^Op%SBv}ha5*Zt)mKR9 zS%-Ct)`W&}wZQd5?hus*;b-f4+U=gQm54a>4K+TrS}Bn>?7wHdRF_Y#r>K~I$OpOj zD~w91-17OJWlA)sQ^t&(^62iEH&+GW=xU%sy-EHXTm@<2m939YX{y*Ywg4Rc%ir-y zL11q9rOI5wXW8S*{ukx&0u8D%pXDP)itZt(=R{ycdVO^Cma|NCFu!C`!Fg|?TH~i6 z#oV<1$4Eq@;y>-F7PaQ%U1iEgky93X5u-hb(SyOuAfxzQ<>qgkdNdbkZYesby~*W! zrZoP61BKVI^cv%Qzs)BOrs?M!stZMb9~Z4QIBVnBM#7`BEjKtD3N_ZBMU5W2hK*16 zyM&sk7RP1H8cr9S&ObPR>nfV-mI!a6jg-q0*XbhlI)aEGow77VPgpUG^zpA^DT)$u z?)PvOJ&Q-Fh-Us+c0#D&p)aJ+u5}OBqbeo(km|FZcC_;N`iDv7Gb0TY%Pt?8Rci&g zL|q@d3VwqIBQFxwtF5+VL_#l{W4?2>w#<cJs{a%VuH1+0k4yBFjnWLU-4$Eq!el}& zKPe*u9ppGf0cif&eH~&lAAZ*UjcuA6A0-(JYJN6d|0=u!>GG`ag3h&ls*TutcPHkn zlRwq6*9*o1hB?rEoKeM(+0FRYyEj=v^CK*S;nErlwlGC>MjT10-1gs<kT!j&^s_D1 zI3FeouY~BmMB_DHirr|!Uc2aIawG5|TGE2Gy#<$!ek!@jwhC@~Iwh56c#Q7%<rYr? zAH$8JseOuFvC5;vUa#b|d0J>`K6yQ@x0)!6PpIO(NFbiUkW=>DF|b>cLVeI`*!g9q z%n(OIExp&Bzt7({L4rTc=Z4(u+WEt?w@4BviPQMUXc}5I=oAkp5%ShajQ^NvSyNrv zeTtdNi{1|f9xL(!S-lQj8oBa}HP(w5IHlZ?32gE-<{Of`e8^4mRkrC;m#K8oMpB_a zkj^^yhq=}D0EzIE?rtzi>PwC7YEJYvOuGV7R`|z*b(1A1dlnxzS^`N&@edE@+M;Xz z_`~r{+XRy1a~I_vS*{{VGH8obGf5=2^81HasZC>by<X=hXO;IOm*K-5KVED@mQIL* zVQGYTzp?_6>r1gUgz$SxX=(`%)A0}BHUXgZ6IVZa>y~me{>phbTmEL_{!<eMD&7!o zH)ZIm-Q=nBvJD>+m#AltS8vLX(d8tLZ$p*VrN0Q@dk3v&NThPyW#X%<e)59m^M0|V zP+T8u^OWP?6SoTE=~!giHwZI`M=4id@V-0o4lYx6Ice2la3<v~mJloxNqsiq;bFvp z^)!ft&@R_Ia?NC#&{GbE&l>QO<Y%~jh;j86Oz&qia(}F0ECT&)M!ekdELj$x{_3<k z<XRPC5@P@2AIBGus~fXzPp?PM8^5W6OEzwt6r6Ucyu26eLQguq=&Pgtq0<_BaIOhL zf4Jlv8MUqMeHnQFz!;>$6S$EeYP1Ps$8S26kO`v|e!c(6H`<EqmO%C=^65~f%;@}H zKI}LupU*n}-8#2zV++dPXCysdp?Rf7d0iX%wQsYeKRm|s{m;mXr9Y0UJS+12a#Q!@ z()}=^&Xi`exBEmVt{1MGn$ko&+r0b3{r7=sH4E)U=(*66cWbKCS4`HQDQOc+;=fy; zF%Mipw9F}o=*AkF<SwLu8iO`pVd<^b^IY4d2mZCwraRHlmjGTaG9Z}A9SRY5GoI9h ziVRTS&k1?FH~Bcy43ws%9lm+AU&Gs6H6`I&IQ3f-vb6E{tUhE&o|W$nv)I%OeJ{pG zUmxbC)~`}e$J=k8babIc3NS|xURHUMJig=}nYGr5P!n0uK#Zy?h85p-N*?h89eZQ# za5*CiRT}z`K&BSB)4fdC#F-|s@nYY;-FLT(_bFEo{X#xxxDS|0FRb35Y@>dc(D@th zpZX!Cv6%?njZKy~U7hgh>_*#)?F{Lf(=#tJydSZCYhjdpQH%jcE=UiNuRVOqeA0e> z1~bGt?{oGk*M_j>g!GZY@miOKz{ZRJ8bZ~ArqB5V#`kQKT*w5i4~$n$yYepwW7El8 zBhQ8$OIaT-iTZRgE&W$3inqQmTpli-7+z`UeBP=B^xgwvij@@=a|uFtBsXBbQ@35* zdsX{|Sq0`>Vm|M%SY{19Go^kEVmFwq=SL&O^N@S~mGa5NBDKO9_le=}Wbx6Z9=9ik zK^P=4{gQBgRUoWI7~k2{(w9puPbgmIwn?wQ+rTc$<n&e4Y;bz>Xfyw|L>`)y{x~@d zwB64ZYY*;>BpMdM(Z)7{0-G_`G9}9Z7!toOG{Bhg)a_mEL7qB4+{3MjhQ97ySlZUd zVARmerA)EQ`2pO6=<nQVnu7Ys3{wZsK4`!StG_5Wa+d>kq=uaLVkj@ksaq4J!%ESS z)g;iq@1*AJomu$)eFO>L0I$VKb5X0Xzc}KrMKCWkjQkB{z}PIv-0IAiib#Jkq<!eC zt-Bbt->-zKXz?pBXr$hE^Ye_{!rDDA)>==d&d!d{W03H62|jl<p)d?mqQn0V02c`W ze4zZS)1~s^y{DKQp;F;(gh-5uYL{WUtV<QblvVnMwFo}g5E8&VutclS&XhXxBO~eI z_WL^pp`<+H4_<PAIJqupb)kw8%3sJ>v>3=;5AQ+R+Wonc9^2rQsPEjHm_&loLNhYX zRq+hWIlbY}lCqY$Eyk6hOf90hArJXO8J*(UV{#pmfL{PP);CO$4DauH!z}7JRC}jW zCKt_elCEj*DDTPPR_thZo$33J{!Wh1o`5tqB2<%t=GVoKxRnwfe(J#6ZdT{=U7?=s z#|ZjqRg>;sYTA;w{myPfh{VpW!$$0-qaHuvyK!NDDP$@mAd)W`r>)uj+7O-aPc7W# z2;D#&o!XyYgkC=+9XNnUpf*2!4L<2%8jqSp?`@;Yu|aP*$t49WbpJ^R8?_2Mm-2Hn z=Y3OFK5tp<(~PzDHN)?9hrdCGnX*4GM@At<SNVHXA_@ot=BbE2WZ>>yQITEO&&c;m z6j=9w-Bus=>dj^NcD28aX6uY9b$_eSO)IY)F>>&UT5Vp!4Z_(iP*-f^owJ$3S39X! z7=AL?n^;0NfEf<9N`pPa=;lj^FPMn;+F~)<+GY!x?k^myv0gSBv#@PV19SdvzS`~8 z6EgYI&)r-rcrZaUU$tK;w;|6)Q8~TnL`OomB6dk*Nha~p-BYGP&C@6`SRx3#Me0j7 zxjmwvBTFD;=|nIcHfr|V;)S$V3(GT&x{9n*<5ZsO(A6!pa$bL&`tC=Y=e<d1n8>H2 zspi`e`jWdMCq)SjXBT?!L?+i4N2DCmdZs}T2??wPAs}C00&@y(5{WX94}X^6D~h@F zc){##PTDvKJ$b#~)lV<%E7Ts9j-}_VO`L6)q8*C&P4#+!$=#5>7iuxB`gqK-Zic1U z@A+8#kWF8D<GV@*8zqFWW?IjK=j%$m5>>~byDyS*RV<j>#wT$8Ym)cHKA!$4lek#h z^J!djF|%u4-?XYQsE=p{NI%f5(6;WS+!c7*b3E$L)tiy?IvQ`BuNLBL73)77tGw;D z8vb+bt~?_wI*yp@S%NcrMG;Aj*;cPCpOWKb;h|!pktXf5cwg_lg-gum9-~&Isnp7W zg@iD&xif&ovY?g_!U7oxi!tgRN%(Cck}kp_#aZgT`>tgE(~?&zdWsN2!yMK`4RT+E zllpY>Y56XRM7Ie0ALn}*@|ZY2+Sb}!{?_$QOjHHL9O1Q%49Z_@g0D|sT?}3Yb&Hpe znBx{@_~xbx<PC>kj3E4i={~lk9J<dKuz$Nwb0-Ql6q>zIje_z&OTvqTtl`>bijx?H zel2Tr!!G5ELj&Ily$1`^vhCedQ+@CA`l$DmPFu5GA!#90v-S<>Yj7y&>>`0WR()Tb zE&YW<u`nSVDZH*Gq3=g<Dkt9VR@x+_{Bp8yZhHGKZ@4;CsmK59J<mQ;pl>#E<#JFV zgNEx8D+8Q1IPZqy=WVyy6p{UMGYeT=?@G>pzaLsTK#CetNqq1T5(V^!y7^A+6- zSzW`@JQO=SGt&L2hhITD<pp0a`0G0Zc|eK;|5B6tdTH@88ueD0=wuK9T`Z&T;4esk zgGcduIJFd=9!X-Vtwor`S(%2C&}kpKQYbK9pNMDD{h2c9!}4vhChNsajnr#f65~oN zT^3>GV<#yxn;KaR5t?5W2B4m!+<P*WPc&GpG-;5**d@O@Q%MBRX`?f`hhNI_{UG&q zt6!zZplvV`iPgSsgMUG4J_>#%1A^pA7jRb>hGUy>pGe0w#QTm$*MbZvYVs8eeOe~E z82QMAp$s?thi6%{&2iFTuvPm{M~`!^u_l%(iJmDm^pBQB;b3$*C@dxHPxUmC&3iC0 znbpz0nl|PcrF%}BP5Y{$?-;7axo08T_A>v45dF=Ucg{1($;8or$o<{-k$hV2I&i2P z=+2L8L($mwFBb064U>==19Cn+?GBeeFevzcj?nwDI*Y3O(ubYT+oO<RRH#fG$-UWj z`FKuSLLd&JgafNav<<|3EOym7Xxh;7flA^W1L})vmbnYUM^SGd3}u*hoj%llc~Utq z)vZ+$yAgd{M2&FU*iA{(7c;EDBfms8HU`oyB{+~Zg&&S8eOP(9PxqXx$1Ad#l!td+ zz7}2>yYn74I!}JCzXR`koV@&U5PQAmT0#GNo0yBzx<n-TCIF5+vZlC=j=perr{X7W zg{qdHMT8(*&tE7w9<oU7$2(bCYIP(ioz3HGU7e2^9TMJtgBgoalD4@W7<9SuhZLS| z2S)Mw!u2$~C~j)~_LMLEu=e1o$!<D}Hx=)SFm{o7;e#tX>nPocg!t69gx-fN!gpN` zSP}32peR7Kn%1lriPSxLTtY0RqbgsYxBPBIVYVZ!z)_3f_=m=fJyccj*~gQ6Cv~;I z8<au~Kk<UEsK!hPU&M)=f7d)QvM&@2)ggZVnJ|ee{t=e+jS_|por+s8DSw`j$Fu%u zg60U36OVSq79Y+pnmS^I$NGlp^|;Xp^vLsYFasjM#y23`R**H>hNULyx{G%x9I-Pt zE-H#u`x&%Z3uGE9IT7Y|3*>r^3;u6h#}WW_W*zW*R;T$-W{Qm?iSaP*#lC;atPskx zhC(Mgcq1+#GHNR1=6JcVViwQ3e`9LaexF{%5V3+s7uDNv0bTb4(LWXB6crLC39>aO zG&m1h8CXJHn=M=N8G888i1VTThF}?a>wO*J0^jvEeT?g%O@A++AZx(*y+w~gucP-M z3N%>_FABnj14_T*N1zaKS`Kg)>36C<G)&MpE45DV4zeJ_z(o8Ley%yAeudKICY^n% zG+EM}^=|buSQsuSpCa=m`pSdZx|>t`WI0nb+#jV2fkfc~-C&RiGSvi}qM@2NA7_(G zN<#sIKD(2<ewi?>;eRj4p42Z{R94cLTTTxJ1>_l@huGlKrN_em6RoCO7KsF5us!^f z@`8VXt!`oRh7oX)0Y8?1xRm<O7y|s;f5bO{1AhpLOaBpHS@sN6XbkZWmwsbOK!xx4 zho%$EKjUFZ;{U^?GX^YBG#vspVi^x$`j_d4;?kma112nFoPW49^NlVTWcUx4YWlb9 zfUv0l;ZjkY248T;KU`Xd=wA;8$^PTIA=FMV(C`LYry)9`qaQfoAJ@f^+k=ID^AAmT z5TfnC{{P?5cS#Zc)M&2Ip85h<P&a|Hkk>FkS!Y>xAmG10B?<!=U{gDZd@xj*4Fmm^ z?I%F&8`crg;rAa40NEH3h8sw1C&`BWcNu!0K3Z5ifDJ_m1qt@QMv(;YYk)DLYYfW2 z%fNrCX@lvbeWE4)?>&9NrdYmkkpxRhbpI|xYw`=D0FeG)L;k;d1Uw%W7v4cBoUWR$ zTqK)VQRK8gu~3ahuUo)Q&#l!a|Nh<HEbQ@50RBJY@PP<Aa;&zmQ2bdAm8+O74e0W@ zmVNDwFj>OD|DQ7JAm}&{6T?~bkCb#3s13gPOKG`I$nj0<eYwe?DdTC3i6Gnm45~MB z8;qo5l4@z{Af5V<v}6AGdyQI~<`~!-+r>-)8}7u<NHG5$?+rib9132{uybI*wf}go zq7U6@M=L$v9Gf6vlCq3P0<iy?14HD{x{Z%EtCCmi9bMH0Y6J5FqiMWsq;u(&sx3Lh zefX{BD?%jf5&l~o4WwA0u7||mgpTZ)vH&Tns#z3d%J`aVQzZWDPaw}fux>IK_i5r? ze+;Do+lG@-?@jR${EDoiFdX53W+fYRn%)I)mW*B?CG&OVjrX7*&JDz_5?K5UzPERP zt&7qmSd)Y%zo7jMeh+mW>3OksZHq+6Re5OiV@yBJT)xVIoEwEcaS9NQp9~WYU-F-B zoMHRIt-($vC+oz;;-02FK0ja@n@Hmc25PeSa4uHTtk#%H*~8|&wS%`xdYky4M@Aoc zjn;r@ZqFv|Wkc{@1@~@C!9KS?&248WRUS{^>g1EJ#8=4nv0{toz2*W^)_(>-N))h# zq5Z-*GWdkz=p`_Vr{7<wnDJfO`pBHa@*SyoOj>IaG*!awa?=j__n?A*W3^EN8PyjT z2cM4dpGALQkTh2O$yL}-;&G(obGVD7d5pfI1((dt6l*iw^7J)ze|WyrKQa6lgclxM z9ej!@)@vTYEyc@$5@f64g834$KkSG77$g|8hTo>j1RqUD%u1}x?ZwHUsLNZUDcJ(5 zS?3>+w?z7~J$-8RH|r<6&6MwO%5#2(ppXwUUzW8#<uOMEG)#E*0NHH)6RICA-wN7y z9)w7Ajmw{<vPP7*HeWT6pk7db0SsS6%X)|HDyb?L_%rcRwmtZjQ)27WwtWr!%_j0O zjQ))#iFB7@!lT9R=;MM@-cpz4@DhlLcr9E#L$35=H6;VlQVeta^&O7SS0Bg|f|~Q^ ztbP-BXQ0Mf@9%P3fFsf-BBfgQ>cc4NQIq4Sx(Ouno^e%$+`#n13XJ4}L+f3V^<oWW zVYG%D+G&-Aeg#f%MCg3Urf>@KEP~jOW-_r~+Oj8lqwNrxZ1D3lnQb}Wsr#I$qjX<1 z%DD%Dj{kt;<M%zS24l8DwMozP*m&MZbccH%uZs^iefp`pJJ~uW-bU$az!&sjio5~G zLm<z%c|*kc569-$nIa2Hm22_v7C*UH_wbM$>8YZq!8k9z?wIZA!1J`0{st!tGRYt* z{5KNt(nWAsv$uC7+Oh`7-!?F0A`HItWOlc|i9~WLh08~ILS^QTf4;2F4J$HPEjD-_ zt@e&7v+PDw&z2t7pl!V~B5XYPqfdC@O<DSSNWkf)=p*v9mLXDPaj7T%C7dCd%Wt|c z-YnAJh}=j9he*z@0CW*@FFc6nd|szHqoHC}?)ZSavAzXtZBLtq;(4}D@6ECtW#P6n z65+W`(9dMZH_I<%@x1O1hBWjAvm6)~puI(e{cynuG#oO^lWom6S->q;f2%!hbzOx_ z-U(kFyQX3*7zHfUgkO<-r<$fLXg{4CrA|bgsImT19z@!t@&<h#B>%z=1hL+$7|!Z= z6!wQp&(D8!-OW_m*m~XdAj7Nl>|U%A>W$=URKTRP!NaBj)q5RnEp3H7?D0Gekj>O# zf9(v!V3T_(UP!j?n2vo5O|TxT%9oFHQ7?Q9?S}|c`%Ey#GsXuwxgp1JBY{F>UK%ei zRj6IhOT2o*EHa)c_WBIw6S*C>B+VZtGxDHs;D^JceOme<wk<#QpMHu{5U9X2CqaQ8 z!3gVK%zdn`=(a*8h_|3=<6=FWUmmT|W&02ZEtYxFfJVl(n!oS3YhSPQoBA-DsLRpP zwgt{gAu}G2h}S4VM)O1C=oqfLXb(-1dt-S-ZG@FSk=9wAM0yuDa21vMSN7!s-t*w^ z>o$9>(2r(LBqS1kx4x}+Zp%u?Gl6CIzb94-+$DI<=Fv+wzJ9kS3)e_|4;ATft#CLA z+z$DR>x3;``$XXPa~5katb`DTVT<mS+^jslSej$-66jrKjfbfVxtY(lKWh;?%&(Se zc25U*J74m}K#U(hbD^M!h@^{h165Qy#b4yj)5S6*ldqch^vfOU@myq9LU2O$@(Ecl z*kl9;xJ#@#ufCNQZy>WpZ@@ntl8KG(Qu?;X4-naM+J3&u?h@Z~^{E@Bu4Or#Zf#9; z$d$)Id!^T4@{&m8f87w8AJ6JVOUjjltOk4h;y<4g2n^=;BP3v=C|<mFY{w-<J-*OD zsK;pX+H*e_+bt9Yhr+<_9|{l@SS>eH$*e3FvR;X`I#$hYGzA_n)|6$-;6ZRFX_Q7k z|7qKkDP`+=&zx-A)%i2#<L0rM@Cbn5o>BpotpyTXNh>GK6wg(hws4uNM<JpUR>l=C zXqsqG)Y>c$wP>qfjnw>%O7^X@#b`1JhV1LAMdVrdBfb|Pi)dho^>#-)YjqV=HX)F2 zn{(AS*{FP!J1q8j^=Gd8$*6f(temEA)JeS@rWX8Z#C)W|`M9qo(d_jxdN5Ne3JJ2Y z<y1Sn+<04Og8pOl1XoBe{^nS_QVQqQEarBhP>h}i@!V;vyjR~iLf|}8R-9K3*^Ov_ z(pXiqduzY6uRiIi+w4H~MMI_MTj|qZre-s>AtUPr7lY}lQ@ArlZEeGJAvJEhGhdgw zUMH3JX)JPGMv>{UeryYuw?U+I4UJKS*Y^RLyQvPT34$(9_>VUGZ)-emF`}%xMi0Eg zTcV;D5?+!=SR}vW7^pIdL@ga8>V7CZ$@H8qd7d$=GEm74lM}XnG80SEhU`Fdj1}{a zLwrk+)J1wZC(pO9SDRdDyIsHd<0<t74I83l-j3F;GHJ|Mce_q%LDkeMYA<JxX`dc& zI+N>B=es+-8Gd6$Ap02|0%PC2y)nDXl4LQyNsNu8*}m#oExV&@9?l$JQy1#wSM2BM zt%R>KY4yc1>-R*L*Nr58^1t32*RK7*N3YG-d>m=kctq`^%xSF1EH2+RlCn7eyL-mf zRvuwA`8@Wm246ilA57tFkpcv1v4lx!tNFRr{wOi`G~#nLeF}5)(J58k_UdbTvR$6y z{qt2s&+}l}hdy`)UKsZL#_<pGFZ<kDV|nJmQ6fQ4X?v2kbeag*Nu<ksL>O^II>k=k zPr|^g&VV$;dpLsHs|5wD!AH~fW`;3|i|t|4Z}ogOKf3qfhF<5udNt!ymJn-^R^`v( z$DU{GLK$`%ilH*^<u9Eub!(aHN6oIQ4ytJ?&AfcCPpHKAqJf|}2Z5$y+G8<&ofKca zW@b)A0li*XeIoX}LFjp+w}}MP1&ODKS+wT4H*V6&qFo_9$6eMY@pv>~hTEuCe!K<0 z&%%cWYFza0(K`ag6|m!3mRVr&SYX{~A9yEtd%NOZfpd2J8^NkK+<FB!C2p?KjF~T^ zS!J*js{Kj48xhF8G<$$*8O^R}0wV;83$6L-+|f_}NhRl3CF;H#RJ(UrbA(}0s8IW4 z%$`nbq+;iZjb9&fR_y9~RtK+r+Ht+u?e3m_vvxDiu?)w@?6Ettyih*(BcgU^l*INA zKaYauZ0ukzQNi~mEkbD>(JrZ^Ig88f>e=O;&&tD}&8~e~i_SQ73OR9Bi@05mxE~Lr znG0j<{|-3YecTC^bJFqrct%b&JBp$~RzOZcu6RTY5H9({JHXyuZr_kJ>=iUE8D3P} z>k26>>YC)HOK;Ozogw@<6~iRqoRDXq;CHX_c3FKHU{ilC`_8C&_KWQ_kjPeTB1AG= z%*Muf(6bTEeuG9(=(yurV?qyAz-<qt(6d2@>6zwv#oK7U$C0tX>9IpoWDy-0C{L$? zX3clSRV*sXaW{YydN88ARsS@QR^G2-8k`gO_H?|tEaFj3Jomc!dDT8FO$oHA*61Qf zomxDWZm-cQrZv!S@`cTP2%qbQBRb$oJ43eo7j5wddBbd(-MaEjy(3?#(b{b=xSSUy zLGW8rlJ+De{LGOz4KZ_ctMmR&a#U8yRLfCpL&o`3e)NL!^P;I~T7HSHM@7!?5IvSo z?9pGlhShKA$47Rx8PL4L0uih=`b~fI-t*NI`X5C9K}nrev|vlc<vJTudi|DUzwl)P zl2~-rI_+iG<#T$M#Zp@*lhXDr3W_+}AAUrn<+M?+w#?5-%b#-2(n+Ii)Z+4j<juB_ z*m+107!IgOuA~h#Z4vq!j;-(@`+voFtv;G#ISXD76&_^-O&9(Y9{jj}(LDfz?0#GN zz&b|q?G?uV7sHqEwDaqCl#CLY2~XW@M{#Q*5#i^aK1V)c*n@7p;VD{$pMFxSC$b(% z>Cc>Q!H*H)HCHXa@WU^2_gx3i{^f=-u3QE&%t(d%yzKkTCF=4f^w~J&3u0`FkEljQ zVj($G*#7qjqvV?8uZhPCC-ZRprv*^FkX;|H)i}kqxK7lpH6#;lc|W?d+h3bRj~JMc zli-|mCF&Y`T~b;otfd$GeORZ7#I)7pqBZghZI)SY)qNA<vI6l!e@oIvmD*u$40?+K z+uZ|`r<_e#s8jDio1Pb=IuW<+akcl=cwE$D96`)tz-@oqr=s5R`P7OlW>HiW37nkn zal4=E#hxwvbF1gq;e1izkI^sm8u<f(X!YDbf{=AIYHnsae&AtDLQIE~bF5(()3-1~ z^BiFJ(8EV`-SNf74u4Emmy(EMZyW$;4FhoWxs%n7vwjOymMd8kWx@hC*H!il)N?2l zh1j>BSeUi$vTwY8d<n#0y%?h$t;kLF7NgofUwzr3cIhRvmCC^JyCE3MLS$}73F;1w zFZUBEQT6uRxi=#-iVs(RT}iRS8g$&iJtQBnZ@`0;VgSrphlwQfW@%0B(K&_F5)tm# z2LpnhuVmDEtn1x2zmxbLRc7jx4)8_4Zu?#`nOxNb5|_O8;~qr?o&N53U-)(}{Q<N< zp=d?yOMCL7))zZV`f17MG^K#S-}Dx3$>4%u9iz?kn9-j=U!i)6&1#NTyygpn;CkT& zgy8<ZaXwz(v&864Y)=aG<e$ekS9Ue@Wu)p)?{*~3Xz>%t#Wzmi&k72t@lwrP(H%k0 z)6Au2uCHmga*pcZ-&2;=A^UB@44w4enO1`{W|hqzw_0i+ew@t0VBxA2#0<|ot(`QX zD}|Gi1vpovA569wX{p=unoIFpkN?EHvV+o(HSFFJGZ&+HUCs_AIusg^MB^vH*DGy6 zg<4_i<gYSj|Gwi5PihM!-2uK14jikx&8NOX>90u|!lcKp;1Qnig)72Rx00qC#!i=< z<v%D!2c*cb0xLPYEVRyJ`$8dswDzMlKYl}}Du^-k&OM9!eh`QD<Ghc75YcPmgQl9h zDmVg-Hn?K5r+F}(j4x+0>m`DdeWFL46@Gr2`9S!8SWPlE?R$D)-w6<vB=a&3OECUq zI`Z}LhKy^xqsjk7$RPbDyyiiR0r#MmVf+mX0U0>AC@5FWBx)IY*n7I=LnMJu)!LSn z_^KlqfQ9aLW2m5;Zg?x}LfzL3(OT$XaZbZ0nid%%{yQUeu_UT(1FrqF$x^Pyoj>%l z6s{}Ir7m^jOsw2o+`#|*7XXf&?3hy9FG4PCDfgw4<aeeairJPNoNi}g)O5}H;3WU9 zwp-ZXDyQyqe2}hW7BO_|yYU^09{@(-+^2C19~VDr74H_oUB|{LCO&MP)Dm@^i^|cb zA0{Sh@3a^<OP@D|ta`%cKi<1+zpYf8ub|LU5N>~SjN6@A8qoh_2N;V+LjN8BKo$)G zZ;<#_m<*PGskW2|iu|?XX+3)+bqpe{6;8#Hl24UY<Hw=#EI6iG`RcC6JQ&4PNa^-* zl&O#Cy%<rKgDCGT%?{2mI%a%q>Hl_9Q__Y&%`{m7t{ghI#HSGbWQKdu{?ZucK+I}% zNH4!t-zDF@N}^EXJ?~9ze9<b>jtivR=g7l0=%yV<Pw+nk0tSRd3Y*=j5=$VrAgmOE zCK3M5YfVB82Kv&MUO_F^<~rTYAQNz(stJx>=;4L`FU1RHh7Hk&;r8YiC@s$aQ)ZRO zmQ(ti?<V?Xvu9ZImb6*)Z4%E{y2UDsEa6Rh*e7X%jg;DUS}}9S)lST3t;`0Qfe4`J zuXuRF=SNb%d9!3bGivQxn_uJ|$2%IiyDxzt=qCOj4T@BUf7^=WJ2o)&%~!Q%S{sPz zg-b(&ES!*djfiMy$q%XUAY5^8b>qFzRq*tvMYrnK|Ft`ql3MuYsBP`Mt6Ew@^2Nz7 zWH*#q@T<o~vCzBk0swX0e-V=CKUV2`_Js$?64%f0dYJL7E&5Zn{J!*0Os-tYP>oho z>q!+2nB&}0Th+wt?B#VX1c!z@H23gKhG}}`ocRHT<V|52^x1r)&H@Jm^$YAjB8BCd zPY+yd-JeT*O`N>+uBA@SC4rMA8&E=cu$=KYZOI;R`0ISI6kBZt3H+_Vp+rxh`_{zs zJ!A5ydWp^m8_zu%pNpz?|NMRhq5<5$sq+pK`V0h&g$sD34)4*s8zFmaP%ZyE7G%9p zH5t18K*VV^<bK2E6B~)Iigdj9J@+-5#)yJU&@<TU;v6YQ0<(!&i8IV?)qB@cKVk4w z{=k${8#jF46q+Q|zlxu+B%i3kmNbNIpUN=}+UiAQg>VWnuM!eqss1I2xd9%Y>G@QF zd#lbs=La&4L7E$EO6FavXO;YK>aT5oIBYG(+>D_b2$qK>n}$wyYcd$jCDU-T9AX$7 z%>M$e-@f2-J78j2(KB;ndm_N38qfDKz#f`RXw1klDde;|NhT2gBXLLKaesk3SGJzz z<dCnNEgSv%6L+wh`DA#PB5oG$aoMM5N;yPC{QhE_AnlB&<muu1N-A~avmLE;qTJxC z6!Przmcz|nr_Y6PLHy`kI3a}G<NRKNe_w;ur`GcWG?0pz_k%-Hn=din*mWv~Z<_k$ zR5vc=sdxPw4Hiq1?%#4cm+eJZ8#o-~&|wY|WVP4z+{k1X=#&q_X&baDB4K6V1D@pn zT%OUpqTGG+EdEk$de!S+=OB#3hB?^!8ZJTEsGhHUwHL5CU-}AG&v7D{**$W+cGw+G z>b|j{A%`xT4@a&4!<^vMv{J7oSnI1TmVX!P@qFq&+10<JX}tBewaxoWdoFCg@RvME zVDg@bc)zVD=pG9OHi|-#;Rdh^$aF_D;5xsoxaY8>X|w#jyFEF5T+tHEbiy6n&>6;O z{d5RX7m7=XwSLFrJRquWH}M3OwM|O=1$+E2_P(+$uVvZx#VuH{;1Jvc!JS~i-JRg> zZVB%08a%kWOK^90cXv3Gwe~(g;C{X5dH4o%Qr%tMT{UXdn8kWe5th89IcUFCIM_;^ zwbSABf0|Vxm_v1hYZYAzb1c}RUb!rb!CW*>RR7qcpDpVKm0_w7$!4QaDkFhvHIt-$ z5`%S~XM{E&70WdJ5gT<2Rl`t`kE9@I0(F7*Ad6MDKZJ-(AI?8bWPE?`jam9YtpsRA z%xeFc_LGKblkb@FDz{yFzFUWIuE6zni!VO3m}}c-Hvs~ptKDxfyFZ^^`>mQTM9U0< z#WMJ(4nQ^}hPdo2BR!U65}a18J8rk$-c8}f)h&w$73klfQ7A<KNLiNIs5VX0X*ZcC z437^@T9)Fy5U$o6f`N#u7)^OPUYZ7K^k_HS+gAKxSc8WC0y#mPGe=M$NpL0_PG9YK zWaMd|YYl}83!Q#16r1Moa<q0<@lMSm-uw&ZazC**9}9GP_ZNQtTHxKE!e*U4C_kwf zTM>Jb`<+bGfvxI}?;PFz_F*mv9}G6m1gI+!fL22U)?iU6lD8K7T=LCvC!QhIS9$YZ zmRg4%x4FvdrIwINw3?B)O`8Tq544#bAcu;Q3^#+RiDfR+Yp=l7(|8&9ozRg8C$)*6 zw;?nX(h{C6{c9!ddZ-l(JKXNDv&vy*H6Cn73-RoTHqoh7%C=2LW2}MpF`Iz0mB5O$ z!x<MQ%em@Ng8anz)YR?-hV(;KdZ~Hk*v6cSjxUCj%_Wwp%HYEIh&i;iMzTNoFHtC+ zkU%Uybtw4Lo?oPCH)XQWY2vFm&X?_BDwlCsgjp5Rkgh6I)7r*)5rHQDjnmh^;i)O3 z8*Ee|M3puh+#=rk>k<6QPIU**pix0-AwX|JZJ}!8d3v8jXqvU9^qC#ZR^ySPWcfJd zY`m@3D{v`qiRk1BRfD5v@F*ZW75l}I`goQ%UMjXUmFqH#wTUXnwRqLy?G-{G^cOea ze6W6Bsryi3P8LxcYmcTKE!EC=Ul3OT_T?wr_UO73PE(kb`NT8kh2lZX_O7|sKDFPR zpjxvT#*j4b0et97YA~vGYh2khE?D%vjh^5wi+6VX<lIa-8cN^58Vv}ct<oA-J-=Y* zG1u>{<rS~_F-3zrwHc68QHhMTnLEQ)hmAvl3@L?>&GL)@Qn}U=GYsdUEDUON9_#Y8 zEaIg?{E8n~Da@9gDQ4bQUH@V6ewfXAg7_dzEINANo$;Ho|H!t6O3tG-GS0|QMIRs% z&D<o?X^b}bvcaQ&c3AC<>AmIJ*g2zx-AtHhka=a6lS;kh<=P6{O>ne{y+~cM(!Zt% zl$7)%5nb!}+xAps5kkdt{_K@slj@h+>@^u1%-LK?$jwiL1dFZ#<I}<8!mn{TMR22B zdUy;uj&F!%xup|P2UcM?#QK<-2%U`)2mo1)A2-IjBJp^;kj%zLLnYR4<Y)HIfBPnk z9UaYB7fQMLi{ixs1eaP%d`PwS)IJv5%xBm1$6LbRq6cO3V?F&hg=HR-EgSi3)yRBR zI>NF8PrpwVa9{M~ot)&-3%q#(qe*^&AbotWf9jurWR;K!xU&cyHM(~jxdIJ3pE<Zw z63lx`LV#}I<JENQr(+%Fpwo&2IxzT=+AU9&Qgte$0u}-T6+SkHt9-<;*KByP<mcYU zA&E^ORMewsOZ_XJ$m*>pA7_i}eY4Z&IP0*C-~P0gh!4;yu5d*&h&~wK9sE8M{x0h2 zI}fKu6lDb&(h9-vGih7S4Cm)6!at7~pQ^DUD;CLcyRDJwLE)uUF_gR_XbW;ncdV0Z zJ8W!={v&*RdM(_>-V@9IP;9eQZ_PJUyrvd!IF7?oGS-%Sl^h)*=(h@O1K%yGeb%F& zEJK4`lijJpMvGnhVe==NZXn8~I1V^j7ub3@jx&YNlA1{KP%MR-?OI21Id`|(%~6y< ztK<Q$Rm)7AQ>@8&R&-2w1av~?9u4-7@3i!>?HVR?*7F9EHX3Yn4w`g;G7{!eon@fL zO~%8r<X}cTJou)8v@P2XDzY;Uq*4&jRTa!1YzHdz2Y}N4c9Bz*=j%uF?UK0bGcRWZ z_f5FF=8heeYZo=D5VUXem7X+Qa<Wk<<_IGWUtNRIv_Hj%nq4|8U|F@VasJs3x?QV( z{R@44HZns~4nW>rW<DRWQ6zxTjDlrB?>YzAdXehh2tM0gsw@V296JZgq_UD2LUoE0 zPCRhkpgULpj=0~%aasC1!%Ne=`g+Fh)VtGNTII-@sXBJdn*?z5g$E=eLHlz2=o_O; z)_T`i%Cb_M0**RfJ7W$Qcr;v|J!t-jPKKY6VSC_yu5*QKD&j`gk=j<NHXHFYzeF%5 zu;jG>{7m&-tho<vmW;tC14~=8OQ%K>iKXjeOGnR*TQ^*)DIME<Y_V^3CtP1SFA!U| zDWVh4ob)N4TfB@G>TILnfQ~5s$|p=8o#WUB9DYYcx4YFw31{V2H$?op@_b2Midw`V zF$A%UdnMJWTy&+1lus)j2t<Wa%7#O3E7NPGWix!k`tdXvo^tZ^5|Yg`RD(oFkTGHW z!5)xVW?xc-_DNW3&G-IP{gB}L?K!FJ6>!$8%KH#2IZ6Ju$$D|+ghr7)_jdCE7hr;n zU3$DstwdI-Xum`nH)erfYuLG&6PsXLZKu}m_bz+sC*vWby0bmL_uYkoltJjFiRntg zN<+3@o?^r)s4;6wpmsa#Ke@6dw(0l&)Sv$?MB@GY*b37Dzakijd^i?+@O_cg&vk8> zX?VNu1jkPw{dX{7tT&^XtRmDuMRgxh5bHT1pVxAd4NxG{U2Dr0^xYr!WFr=HeoMMu zsiAcFr<S<-UK+G^>3w7tsE=*Z;Ef#j8<cK-Jb)DaZ+7rr^aryE-zxH9Z<I-Wgvycn zrH^v8bwA2?dfPku?Vn^31s@;+eCuMB9`#`#P`JsLBp7={{$x>Pnnvy|`Iw(C0RB$` zfC)suLLht1G_VEKtfIeqn|u!UC`-*0eBj%^KmJ=VUIy3z9dz<w_nVt2kcHoL<(79~ z0#M-pvGw<7pL)<Ye}z)XjAx*hSt*|<{wFyU?55-A3vk7F_GXb6g1?t{v+mz11rV0a zjz_z3@-(L9XG*0BY2AS?P=)jb(&?LGn*TByh=_rpBS=gTpW7j7B9j`B`BLV}ZioOn zm=`N^`sT}4COp6LUczUA{>_tQfw%I*Nwfq(K~aQ31aBH*mw>$o^`M`*pM7$CVi)Zy zaQ_{I4?hSPDI^Fv``^q51R3+5pXAoz9siR-f`B{?^ggW}zLf6<|N9QW=09{W&HrUv zKmw&te$YA5|57RbyjR`LhB~eOH3tL^27n1DAnu_5(lLP0*9H{xe`fqUKmSj&@$<d2 zAq}1gS?<4+%un<aRu_usXE=21|E`QMurjic#K@5UxaIp_04t-L(`oSEhXep301CQ5 zKLpr+Y#{<x=HtA{7wrE!i0r$A2%}v7*Fio80S*GmiX-{I4uTFihybb|_kSG(^4+Qb z&y4?Um;alM|9^dhe*tpwLo7ZDrB>4i8ijm-^wd=2#nUTY84CqflC@6C<yyu6#C4Db zw(#%nl3fP2V^jquy+#?{&`9aPph>Jd`o{T2x5Ze-id<oU^uL=l2o>0*`qQ7Ps2pH) znw<z}05~@dLyeP$Ce+YyhV6jQZX0%JY|Sv680_DTKOmB&SlWVA5ToV4Y3Nz1?x?y@ zb#Xg%d$!bvgtx5I;v;JL&jCU9;it<OGg&U<;VjFVZC~r6QjxOZwJ6Y`>1%P8!DGvY zeGB%_LE+;E!UMrYIgr`gn^yq(9r?u#{euIeMLqkGU8Ct-^A}rvpJ@<6{&RbA14oEo zU>=Q>So4yz(w`|w7W3K3AJ++;KryZ*=oi+%N6lmyaIi3gv_;(Wbu`@TbmYM;wYMWi z6X;UK#cSnc-iOYg{eF??*-tdz*Mzo{!mxvrHQvZM1HamQfB3t4L7WqeCd0=OF(r7> z|K3rQWx$~a+i3V8gjJ=ka|jLas7Tqij;N0JCrHTEo6!7_EzxrkePRDyf+!A18zlbk z^Hb0bb~}TCxpWOUu9tf_i3~b}br!1~vDmFvD^1Dioc=#3nHFK+*@8bmhVnD-4J3SF zKPY2`i{)dH0Lr^HZ&S`ySt~Nc4CNV>YU2^euK&Isg%?~E4A#f=WYMuE@}%d8D#T-t z&vkOo4Ux-<J$9y0X{nH|0O(~Dt+QOq_N;&<q#CsOn&kqFP#gt#@_b?5VUDnVK&LE( zeSkrmX)VsvXihudAs@}rY|hZtb$}C<aVqJz$3K&W0!+J$P-Md6R?UPAvrfxX0iw4Z z3jQy%8N2P{u!4hBQQKbDt@Vz7q6YqcV3y87Ch456VVO>Q0<<J0%FQnaLtfkt$J61W zKOARNR6aj0+m=wn|M<sOu!R7^lf=2HJhfI+n8fLIb+GfBLVJpdX~!_OLRbq9iy6*E zgRt4$pP_wsxc^Kp3L@aRn(HYwh6lfXfn(KD8w6h!1RnelW0xIpRQQGZ?g;B}z;%LT zL#B6WJ(=4m7kaW(k7HXL)PR*`-F{U%um7z;0i%-R3wb!$SHO;c;Ft>2;ao{>snl9# zv&!owe~}h;;h0IxUO4;d_Xu+{9Pm}cC(O6zQJ@6!iKSe#u?RKN9#Wb=O#`M5@Ml2H zVI4%NPAfK+j>~LfF|E6@s3fvX#pJz8>zn5uxhleaiVDC9*2MELfD6h4E=W|XI7yxa za4SBssJ6Q0p)!m{=hn(iTTYayMWcOkR8xMmw<}_L95OIjtdS!Rjr3gD8A|+dbF^nT zJ*v)P|5cqAo{a>h+}>iOE|14QnCv9#i9Tx4Y$!phZ6}tx!E;DoCI4(Oeryq71!0t{ z<iEAPd_3|VRV(WumwHXnvYi>zx^UA|Z*wTRO)0$6Q#PNq(&ZUz>JK#||DoAzB`S02 zmE28xH#vb-y_f0PA5V2XE4u=%r3pOLw0F8zq2XnlP802*cRZN%vB%FEEY0dTSNiq& z#rv^nHEv*w=fz>jWDn>1h)*_gq1u>D<BN9$#RL17L`aG(JzqDA)#Wa0&ihX8l1`<J ztd_-(0r&zIHX3c3e*s9S`U+Zmx3($cVaIM|kp}a6ByCJJC*XB0<&Q$S!a9S47sp0B zz=6(=7n|TMXvpN`IuL4O0e6AS(u<uQXdg=E2~ViydhXMW`3yx7I*QOgAhtWHDKBjl zm*t$ED@NSEEdv!Dk@<GqS2h%fZT;5Gpl}*uNWf-V<?HYOhd~|ZT(hx1@uRM22W~b& zt^XLnexgFi59e4Xa3)a=E-AE@SQ#eYgj%&X4SZL&y*GQ{G#p9as#D7=cLa<8_S8Lw z4=@wgXzR{z=vZqf1vN`30Z8?R!oBrB`kb6LdoBv6jU~%xa@QRa72kVo4K@;~oX(c& zGi%v%WZ+jKDqOog@;PY__u5;0TiI?Exa5p#Kb$xYG|D?+YE+v!iK|JoNBO`DQgFl% zKlqmGhGH>DR1(wvDw3q&a$OK)An1R69Yo_c)hv+891+oS%ZXMNuBxK0ax9*q@wOV; zb5nBMUv?x~YH`Iimec;@Q6>0cjQbA9eZ8|l=;J0T0G#539*Lx#obq6Gr6LEvke>mv z5VK)3ZCyD~?b3eqX&Y}LOF5t!-9tzIGVNBJC!j$_VF-`iC5Xj*<5VK*Xl~dLgGTww zfDZFD4(na2FnNkXw&>mH@fPx%r9KxxRWKiKC=ND?kE$$O+n02DZg@%0EevJNpwnU! zCS~NJ-MMVYO8>BTVW0kQY19{8j%_F1QCWr6>X=Wm3XqBY(fas-Wn!6B@y6)~#6g0g z&QssgaYXa-iNJc@0OxYT$d2tz1b?s>WYqS+n!7?Vnb8<+3Q-Ci4E&$QEeWYh@rbY@ zZj=l_l*XwmX2+HDUD82wM|`0yA-KF{GbU~z6WX9WmT!T{__Pb1%S80Cmai=?)yy@% zk_fj&@-^3`Z*+xf$6EC%+%WlIR95QM$})=LEkDJ6&-k+7QW32ztbLH)RdAog+jaD6 zyPSGWYJu9F-#(H**bx-Nt2aGRY+Q30(|Z-(FxUUPJMcsF->&E`XhwnP+<Gd3m7C#d z{5?R63C0Y{Rkt8qUwY$!;_Pc>Kc{3eJz7;nA3^I<o&oXFFQ_#)K<1+T%`09Yn+M9O z>$*HNp)V&XYV>rfI~-e_U?IZ|am)aw79)d5z=~vYCQCp|BmP=B=+o=t_K^OhLYlHO z%48saumdQhTWF%razdyQ&}QAjvfu8P6B%=JK3Pn^tao?j<+54#+2f)VbOrwmbkRuo z#Ltp@-45X9OV0RM=-VVm-Oy^E`{(6ySN2yW{Gw+v(6Up@4w27;CzP^XTt_J1l+&4O zdl7X>z~y*^9%Isme8&MhSIY#wNlwwRSuVe!4TX9?)z=~aeffbJTM-wvWb&$cXN~m^ zd&IC>i@7@XojM;%eQi+shnYx2qv0=@ZMtdTeZDSW`Afw*C`Sd#wBWkU^GR}4Ae)8( zTc_H{GB_qJw?!dSdjS3`9=pxBY+~XbQo%}dXhayRAB0HV+5C=px91P9vyd@{DM94b z1GVd!M8Z4TEoC19r3OR>-nXFOo3Xn9bCv1@<K$}{+XWkiMQTR(y0@9{@zV9}3h}fi zqp)!ezCLz#MO--_6_9W`A_;hKnjA%u2#qkRs~lRlC1nehON;F8>NBvf-c0-{f>XiI zUaDQYNCN4G`F)#K@Y&*PO<si*q5($V*SzlUHD~M{1~8V2+&PwO=riFsGcv!S$oie@ zt*)a#^jXf23s?zhUf87fJa@9+?QzG^Teex}<h@n+?$gGc8fUa+zB9M<uyUsN3c}+; z_#K2go+a!IWLO11CcesGrZJz+<|IA;5iXF))MvJs%J<L2Ty3s5iSOu_lqEfg1Xo1U zpFj6zd1ytC2c%}iehUkrq~p422w?C&oBRq%vsE9#*~m<`of>=HZ_);EJ?4vm+G}h1 zBC;kY!q2f$^hU68pJ1{ilbM3ent=Y4BQ)>VjA^p@%bifxFLWApq&BU$#{+B*4kyYE z4JZ_sq93@^{mdr`p!#99$B|ws!B?~{+U=pks^~rsaxt<+vTfT#TeWPMX}ISMAG=FW zy#6#?lZMlrPA%snRE42R;<QwzbW;>(wOF?J{01mnCr=jnH5C0GgrU>^#}KEJVK2yT z%W9w~DVceXY(8|U{9ANvRb;j*uM;06m@G(Y8o{4&p6@3(!<6yTytbNViz^a&>15=U z1g-NHOM^GV<MMVA!7az=(Vo4J`0L9c``dH2D1iW8=|m!j%%I-91n24f7G0U*%B}fR zcc3N}n1VVAB`OlXl~s6+4|WYoitgPR-+CeW6q<%S9+)duBS{6LUJ|#VhzPCgMq}Vt zd3ub;{%&Wgp|;y5oz#7YK-anS`V^A`@!>Qz2PY7I@)6r~@!lI_=oF2smt|E<>g9}N zF|98>*OzzFQ5^vDlMqJVf0q4>2gpVa_euUO<#5{DJ92)ptsWX6u!EE~(fJr^|9!I! z*>y7XYny;Y4n#y+mvN?yk%L3UC#&WgXitUJqc=AZQc(gz-b=TfFrv|&E>~e(I`?a) z_EBSWUDU=WnR>NtA;Gps9OpHwhC@*!Ubk)WQ5<}-a1<TLkQWV*tLv)sN0oAI-&*sz z;CQr*+OJL_Kza9Psn!)lj^SekxKy?+EC3;?CNr&iBe~z9^A?w(cK$5{DlwHn`$ARK zWb+Gfo*Nv^1~il62C}ZRj;kRhBWXM3J=NX-oLzfI93symr@u9}CBmWk`PtCOht|iV z1yaRy8kv@Zk(?Laiw1btEswQFtZq#9J!Dueo5+K-?TOZTXQ2!QmAo$j)#U{dUn|F* zNqaoOYR<NscW9)zzZ)QdosoF$THGjAIV1#?B3)R#DE^f%@p=(?%uKr*S;k(ReBn*D zNaZcVU#yhDt=ateUgsV?UKC`bpy5iz=XL0hHQny-m*#JMbX)*CiH63PG$0hOtai)H z!RI-$$_t2~-R;9{e((~I*FmW1qg`BvLu(JI14%vI!zpNTfDFE$wRJnX_Y4S8q`gLJ zYhYaMPj_U&zyv?KrX@7Ha@4QdwHm|t48^pG#kTL7h4wn`46-~zD^y0<_4csI>`S3= z?#O$P2<?h;szZj<LaZA;%z0hbTl-n9gtG2TM7j=cU(|uS-<}#mQ49~I)PZ9r!ys{< zVO5|=5tnPf_-=q|tk;4^(zl+EWt6+peMAYdNsJkrieIjhvW<tYskXk18e}=yZ$ajM zg8W4Xe#E_+yhvT$uUWskw8HRbV=VQA9DDO<GOv|U?rgp>wD#zWPycV2rtX_3oK*~! z7j6gl&8(>UiM`C%!1RSY-#oGFPr}O*ojbHpQK+2Yy^CPyp_p_GQ%u#=%og*0wI&Pd z@p)7GqI8^S_Qo>Cn?m>w1MPNsgCYw<Z8z<x1G3pc%vQ_Oi4gonim`kX2gP>CJT7dh z_dA;6oB<<?TL~C62~=lDMP@p-$BVW5p-$I9>wdilfh|NO;5MYoTE&W`n-Pp4m0FNt zP;4)sj(dofOJ`$3!gP^Zw+*xqhXhz)m>x;l55hK`dnjJFzbDFjnP;!1zPp?8JlkEx z;qWWxQ^oV|nuxhdsHfA7y$X2{%+~KEt1KrvZ!Sw@LJkX#2ecYo){>bwp`-y~qCS3% zraM|U`iFx)!a`N<iN%^Dlk;+&_R*j|;>jA*9~xgvM)lckbTfBt8rB}#tj`Eu$}+js zZ;n`iy--?5hnu{LVlvSJm&$C~#6}#sJW|Wl1<TjC+QMkH7<adTZH!J}LUvRj7BISe zXLnpy0<=%KG7Ts_0wOfQohp;$jVf=i<T-o<{n#Hb)*YJUaivmuQ^T9k%h5s_gismq z{U_P?X>;gC9^lk45F&eSK0kF2?mYSlNlaWj%P-arJ8HRHkXc;ksT_Ex?cOXl*rJtx zHr;xg(rUM-Emj`EOW!*>h(#O*f}s{4r<3OM!Zwbn@AE<}+#jpt6h2p#HQ!eCAGxl` z&`0Kec-%*ps<@``0*k_`a~ME>DKyWxwb!c5?%&XCoqVuWYqWd)OR`W0+!6!1LiuN{ zZ{;Gmf7*VG-yLUA;liV-O(fxJ(c=4*OzkZi!#|a`rI<)s!5|f~b=Zn#xg%eRvN0Lj zkK36~m+Xl5{tYj7w1~h*sGDkaI?2Y!K%<CgrskrOWLvq<2}{M9U1`)3KF&a18gL!h z8ug*AwsWnR39lY&?2!e`AS1EDSg2{+cWk(VesK2CcH2QL{`~oO;KK<74a9*&z;=n} z?E@*A#8AR+J+EZ)cfVi!l@1^~J3AiVY7v*+vBU%(8aY_WWajABr_t0$!d5d17`N5Y zbTAGExC4NGGIv7wMfW}MF31`9YBX%SZL6Qf1M(7-u08Y;o+7{N@H`#!N1iHdTobA; z=m`(6@#P-mM;op?*<IU9Q_Boc-kwnjcPKR<h&j`|8VqA-xo1d5H{~2GCmamWabK}4 z*;B(x?)T8~2@Vo6fkl^q=|JW*Cvh!*M(47-4$>Qa`ter41%4Lkxs(-*dJ4;Iy(&-I zM=!kxWuwu%_ZZs#LQGc|f(vSG1LH4e|I3KSzJF3XM0xl{fBHtQ&@s<`pKPva6QOJR z_f#YK1$j7b(xf)pw&M9YAY10bywhYRJn@>qVULx+4MSXGGC>;Ta%?bHvZDLIaW#*v z@!<ot6OvD+ueS>qy}D{mBSn~!k5=<#quEp~|5F#C4u-7d_K}^Dv*)i?m%^uJcm*(C zG-?eYC4j;|euBfubo20~e5%~4w#~g2sG?<a>RfzT>{aPRMPM<PyH*zL5mqbWa~gi8 z-07POtJ_9QVKmEqfNTNU2_TgY#9sjw1gBmsa)o$mVe3;(?&ChaqFJQxk6#o$od$83 zPt6kX)wN$l4yY)YebGt^=Q%*yNUzaLmUpN4<nmDie@~9Q?2WujxggG3pA!C9h>v%& zKTC6weFX<kx9b;-s2G0Nu};NWs+I68aGo7D%~uNV4vee-Dx~qH+O-MA`hb3Ir8I)u zFMX>r*UX=D&E8hBA6X&j)eO7{1}%}@^2n54+3cHMwl9EQG&uFNyk|fNSw9)e@Nah{ zFILfG=BjGVg;K4iXRo0@%qM@f!qlsWZc6Lfut+I01DJ_8Y`t%qhG7*+AOCQsmHz34 z<xElR32wKI-OY$hznPNT2NA1dWZ4V^4SmA@@)_C=vd8Awq(aIeo1S2;t<@yZwp&DM z{-Jc~vLueCo`r0S8IVSLO^FdE<cyI)kkqRpb~w~@F#ckBn8=zoFjl0{Y_uKEesruy zW%vQl4l4D&@ex%C-u}Cv1VcNO@YK1U?*a`2kI{JVj+5^v-+oa-nVQ;7pr?TCvb(6; zP-WR7&76O*&->Acw19xse6hb`h59omkKT+7y~Hb~Us`01H)O~RJin^5)8_U!(NQ-Z z67RRymsbs;*yr_^u2%3h1|6e6##{N}39fnuX}^=6Bh3R(&PB1jhHRRdJ|AJFSCIrF zn--KOCl(vNlIHJ#Ih+(N{8sKB>1i{Geqf_OI@iM{IeIobEJ2^y;;rG6`YPN(rq{oI zE(3|qhBfFsLO%lEBT_&RfInNFY%Wjr#wwLufadAutP(8{$_W0>%|<Xz(R4bYcEcM# zOS{r4zUAut1Fu?T@SAr-`qP`3xKp*!$W0%_Lf3!~l_UY&B{c*VfU?$F^)(=`ZsgWz z_YP#jXK>h?tzTYU9zxHe*8Vy^rcH=fVyw~Ubfi|Fc$nOc%3OPW)mBIj-CbJSNlC*0 zc(s>8aqE62p+zPCCyIg;BNBJ9{p|s`b7Z(TcfVbfsW~_R-E*C>(iBFn-!O;lVjKs@ z2L2RfE+6zz?6tqGt{KLZUnioy?MWbgTLnO3-Jc7a!dH@g<AbqL{;H(go=>-jXy;XD z3Hkf&=UsYDB<p)1lCoj5%+4<Vwf!BhuWUC+;X{v&ZniN7%P+ili6^v5)ERu9uDUva zD4Ru7c@4LKrt1v@?M(}yZYSvqq!D`F&#f%&!3*RUK!iQKeYU^{bT-kE)mhTmbsbQe zK2#><WeErDgHR>LR<Sf}ph@m{i#0-i9q0s3MPzRRVwb^UQ$N5I0{VJF&hk@9x7Tu$ z)Y>PK^<yR;-UI{#Z%ciPd|D(RH#y*&n6(Xx)$>x4K9JFSPm5-RZGUT#w5Tdcb<j#} zo(&C%7{~t!fXoeYc~`1Z&zhacG%DvN`*UcR1!N&m11^Cq521!VjH`8?-mz-Tt}5lH zZ+CPuukV@JfeP8Sz}sE>6L#v&jVQIU3Uf^B3vxU2#h_slQ>{?o=w9-7hf`h-a4+!E z-2O=Z*%Gxg(Rg{0k|CHMIzKj5&J+t!spDNpZx6pR3xBgZLWjovw!})OkQT&xGFBO_ zyGY|sA^G6YfaaOnX&rTfWqVVMW;Y9qjti3|zmu(ESyFt&Bbwo`EjG|B^7e72cn_yb zd2BNf2{(@m+{w8?8CcNFC&G2aZcUNf(*^S(sx8`j-_nYqVR(8zzGHbU6AP|d8JeN; zV$XI9^}+RHMIxTa1eocW#oWEycrMp-%h{63GKQsYvDEmQzE1`a10e#lbi2V9<Rfk& zVj_{?Exbso?AGA1D)P$-*3`>_*-}T@)!h5cU4_4j2>kBKy>Ap`gky%|#CGE|8Si+0 z^S~>$57JU6T4o`C9cbr@*1>4s@4AvVczunWX3J5m%6bs}x03K2+9%3Xg6N~n5<`)j zFmjdTp-J8PifM?FIWg3H-pf4!9X%FeyxB80zslo}ueFV8D4ed>3ut^MAJ$4?A5oHf zYX<^Cs23*3WtY+}6CH`#Ug;|@dwoJN1c0~mRis)sk^4*gA@iklST!8n4RUj3&**wx z?=#L;4!P3utsM{V?Cw?wU$yH3n4d~fJjDmHSbmH7EP_<FJNuvV=r1?cr+U_{F9N6= z4kbVO>W)J%tP942#|urJU#_MHCBrFa=R!-bEqz4^Ull^s891L4=mrO%Kj3@OrScg6 zlr*{?UNzfVJ&&F<b+_Ej>z_w0vAExBf9-p9>4TukzW#3f_Zm6*kU#&=lu_kGVqP15 zOg5w+|34TyVP;amhbrD0GI5HIk!{*bb|uTp?O=<!(d@mF9)>|tfS2TYY5o)M$6yZ1 z&bG|s)-fo`6TJj_woB9bZSK$9Kutk!x+1E|C)OxdhFCqh1OLh|7B&iPsu8$e6Vh@C z`vTjogS=PMFUKK6fuXziA?|c4v_fU=Nqelk>n#%&2UYt7d`-1Eq~{o+qM!w}_{m9S zW^5L7^|iVZKuql~E8n4HN=<15&aNSYHoMN+GKI`5H=n|sgUoAkQNf&@DgW&gSn`tB zld<Q=Y<u!wkX6L}Jt&G978LjneP<NUn+aSH3ukr1k^~1HN0!b<j?0bq^&0k49wX`* z7@tVYa{i9EC0#d34X5zvFc1QSqMlz@@rY%guW*WXwsS{<l<9EuOKIDolqjv=4pmw7 z7=ErXb;STc6;V$4AHB<Z(KueBZVFw_?77o8UiICA9ROjd|CwOjuEQE1+_xOEBiCGK zHl@N<-q|81xqX3Fu;bOX?L87HQcdxi*?Q#@o7(VtUp?mBc1m-*(s;M})W~M>0UFl= zO}szzBhhb2STa9S6!m>SB;qLk{S{r@yH$6nW%t(VvD=$nuD6?6lhPS+byJnac!%}} zk6D_LmSoqf^c&M%)7=q-Lx^9x96^>JMA~JwI0NPD3#|*vx_c!ak7Mgiru#cr-5+`z zhP(xh2*G<-`FoulOx6MtXdjieOYbsdz!f=>=4pHoB;XqKLAq4Lff)2G8=*y4Ay1rg za+`E4)~j7t$t>oa7#Nr?TO_uqB**GO+ueLrRLSrp!yS}&fDnDkJ=#DA^6l&iw1_;^ z<Nj7TPi7Fc-qm1joqK@b%?X#2I}F4|A+qBqKxo;AQM)c)+3mc#YVz)Wi@y1r4K3Q4 zW%qpL-kpGiVN0-H!zU&ONJFDX&h5&_^!66D;9#)`Tu}d#k2}EmK!F8xNI=kk=(MYT z1t5kW4~rJrA$Rh5rPiI~$z_=51wJBAjg==PAY<NVtf5~06v{KqLl03P<`Y)@yv?bo ztT<j}h@hB@iU>{w0w>aC1yi8~XT}XtcKvE((yo!tB0AspnOoMJ>co1AdR`YNaqOm_ z@Kpkn;XL_<24lz<;sGQ;TV6D{>|7^)Ger2B>h~k*;#}pkKl{6F6%qW3-}HBX%wkx3 z4lpt@q7xEkXo2+2cSkgYc$%H_?)?yU9i+Dc+dpwS9*S4~>PG)spX?Ze*Eh5yAsB4K zkMwlNKu;edVy^x6e5Fi{vg*xdIyp>(g=XJ5g;S7<Z8ldX6-%yjq_ADT=0VPm%RzOm zmnP%EZXFT=->rs!2oPF8U>YbkErdQb*N=)Sm*emhN=|<AirY^e@ncqMgbx;6s`&AP zti{hX6tChN(}KL&^LW;p3lIUY5QuB|=<@V--k?q<c=F6--x}RRQG)kT1wn%KA%jY8 zL4`9^W^Hdz*9S6m>UFmR)SmMXr28#$Zuc^oy#9mY5=s&-FSUD~(y>de?hHInX?2-a zd2Rs6Axa^$TQrMCDey;<1Nj38Tuz7+)&~TeBmsi(L2)TU1T}p3Dxha`F4w9KLBg9i zFBI8HZmd%hi2VAQCDQ-q$awr56^rVS(%Xave&F*C@>@EWS3Yn`59Ic5A$0T$h<HKy zp+v{JrxiKkNuz(m=!bt_+&U5;VINFKxbmVzzAsNeRoS+-Sjo}Bp+=OIdT?F@kq6nk zOhxLn<nL#GucW)v(y<||)aM;!@7>?m=f<Am5`*_NpNVJl1HpwMp{b$3Pzo6VF`9~o z;)mZVs_RD<qOZDf#T^G|WetNAZZD5Bym#VkX2_0YY7q)CiEdUurrJGFrmB>1+hLkp zJZ5!{Jli!h&WekQ<FdOyV&Qh!>#N4`lfC;OiV>iE;|F$syf6jz_N;S1-Ge-!*X=pR z6)E#w(WBu~&}D6vhxcKJ4f*AOz%{Py335R?fI9d{+39ZZ=MkUd;#@oX5ud~S_e{>s z&8?T~wPxq~HKHzxSVXHZbv27DCPiQkK|iD5bU`Rg-#nod;m(qFst=$MnOc!0y|T33 z4qP(3ypmXZ86qQnw(~7D)`SCNNJoZ%BYBoW>k&Rn`r3aE8DV$ia*B+EWJvVQcB|~1 zDs-t??*%85ooiJ{c%%I%{u31EPY|rC1jzfLWamhQlMmhbbbc3Y4B6XNm*aL2>r~dU zZc-y}ayaQGhQUB_YE2_*gux8%6%K_T1j(P3kJ|91x7d^}QrErSVu6x2U}-;{M?y)@ zm^VHii=b<=24U_u{)yXfytm@RLj*(7w@Y|_`rc;j`<(0b%!_VkMS1zpW5516AV6TL zs2$T3-|(}q&kdAZE_7n^vAD0Oid7^y7X4IL+bE%Vg=Ogq54``J;}FHPVNYKRbHBTz zj}HT&OXT6I>cwVq{-r(nE5paQfaBv%FQ!Qcn(|(MZ_PjlQ6JU4d$`zV2aQ_0<fP*V zWwV?}pAoAfk_L!QBg!l!SRZ~wKpctx6IZJ7$mIfKyTYF3ujdhpO)-ce=i_N%9K#34 zxSnH%6;#>g+lTJJTw|yTrjomjZWx|5jGZ0c$3JRt9)7^3s-$EIL6-&oZkJ!8&lWO- zxVShH1EZK_9*&g@nSPJ7C%JT!2#&D(?Qu5LmGM*02};ZM1sM0Fpf?i}6VKhH%Yy*V z!^6XLYx70tuVoS<LMYmdFZ~+G65=5|Utc4tx&vp+)Wm31XyXss!y6FsxwOZ9mtr)_ zGmN9wNlI+c{y_Y6S(jHP;1Cspr$m8z-%tr?K2RO{JwN<QJ?#p3xy@G_^h(V}(&+hS z7{)E!E@Ci>cK(o|V?8m<7SmONa`W>ZlAjuBXU{r*dWQ5;TRLw~K|>sj6>y4B$Hi}K z5K`S1VnOl~*}d<oC?3A+k5GHOlO4!1JbJrfe==Z73Do37cvG>qX4=jg@5a2uCRso$ zO+ced=GP~f6;4~OJ9uRz({UWg9^rHL^{UHr>-spmPL}r>6Z!>0f`I?|nEdsj=c{%e zk@tLM<8yzspm;XeR@2?S6re_O7ps6P*>b-b8}~VBWv1&+!FasJv>H8@q4^j-Bs?@R z&)<o*BCQwr=9I}?*$J=XIx{~ZUIW<s`8ov0?gf%%Xe6jaSo!XEcxcAy`4}cMgYS2@ zrq$$d6|CSc`viN?5Y6|UV+i1zm@G{Chcp6Tfs#h%wPEY+5mJ!0qUU+NzfvUDFrhS( zloZdd{K0@_-MXfHNKc0g0b;PzeD_9vRoM6cQ><(`IB50>Q&l|vdnDxUmUrIMzMA%9 zl)|7jskAAGXm@Up|9jl+i!#le<VxdTy>5nVU}t+!V;yyXI$#j2-gj4r9e9Kegw1Ih zPo2$$pyJ~>pVM*BA7t+b24aS@Tp4r*W<~d?Cs=W-zdDQyHUwf$-HD-CBP0Zc-@9GY z8Q2M9@;7h*G9~aLPVfjqkZPca_rN90+4Nca@0}scBL*Va0e^&DN~ABUi8N);@kYV; zTu!&#_dl{dRaUPoG~1r|tFwqcE{s&NA7NF?v>mF82SpB><H^Bz_`VNR3J41LVR`5| z`=T*Bk?TX?bpqKZ9jeP4c^~AuTVgU{z_prh&;LZcpxSus(XV)JE)@9O%SyvexxrWR z%0+wqx)W?H2V)!=JhR7&;H{{_iTmer2hM*m{wS@Om>BYwskV8F`sd%fu_hbg4R>CB zx0#-1rfa`r_kQZsTWO8eFB5{fcl=2Ael;zYX|q|eS=sq`_ESwQ+_Zl@v`eYAAY-cF zs!N@a8sgmnno(?eO?{q0VZg16J9XP7{w9K$dOwZzC$L>H7-$hh^)73;q%KmRSWI<z zxEEVBzvx1GtfH5|9LsY$;gr9^EafSxywUIJudK28dC4j)=Uv@4gntNDq1P>GwpNDG z`}Z%rHfH2xB;Uyw1h_%K=?aM<H5ozdu1twcU%RW(0LF<xTvF2Zi)$QwnVm|R=4NYs zcdxTTTQ&`ab}1)i)lhe)+69F7*{YVq^}Zg?7n>w39d;P7RdGv?Xm^WH;uCH6t@i6_ zKJAJ0K9dJCD8APozJrl^K3R!bjB?S$uz)rV%UXD8lr+hcrD}DFo>-&YVIO}15F{Rd z2Sz!_h0lw<D~p)Kli(HR_AF1SIN`D66*-VV-7&1mq@-`T+z@rc5%gTCKuJS$lX`PS zltm6hfOpX?I|d;)dT`oog~VCjLQ8Vz?S0K_-P*Zt2?%Rcxe>g2yI;Gu_6i_DY6^B> zK={~PL${|Ul%=e-n3jIAUpXk{jA=Vo3;r!A>Pm3<=Z~p&`n~>L8Ggpy^Hjdq7TOqF zGyyE-$xCADYbhS2qQB|-K8&^~Bp-Jq!D5ymQw3}yi{18m$1lw9HY?G1u={_W(keb) zubp{W2pq|g!p^6Hph29E#^dX#1PZm3P3m7BGC6meU1+JOn3m=N&5}dcC}RVokVDtD zD}+lP<X5TGS@%=dO8nH<_&N#^H=^~N1{<_80e-7dTi2PohPkV8rlS45%ogD{m%+DV zn4BF*nla0!x3)E?RGvbQz}xbvc!uiev$9WG$wZLg^hE0}GCul*=h<wHi5!e{ac8To z)&5%+3N6AVs%_s@8?|>^6SdP&BeqL9i#=F<6zS)WB>ZBbdM(|KO$zn8|9S~4!Iycp zzrC8bySPGHHy+XA%@kvlXwqacKP4W0&U_hyfwptaxf>q0>I?~NuL&Q~xXGE6e_Jb` zxe4LK<96_Sylxh1QF@-uk;uBcArbwMJ;vv$QR!i7kY$%!)c_4vk7^SRwSK%HKJ}EZ zHigNH{01l*74bed+Lc1M49lMGPaq)EK6JkwFH~n>w`BzK9aWtqw!SUZzZnFWCBzYX zuMfdMCMe=`ek1hSrynxst8fnAaWqjHFERb$wpHtG5}Xv1zqheg<>;+&_>GuoT@kzt z8<eyHW+7*?Qs-MgPgrl28?&i@*19PCt>u}Nhehni1sa7`j?3q)eTemDDjgh}bF2g4 zuWmo!Z5LeGRw<Q3Uk|_b{_TeWTUZe6$&G3Yl?eGZ2ncWUt-7b4>SubsB5p3wcn2V5 ze(xnCYr4{A9>fc1qKSihJuDhBWZYdntR$k<t`gS`_>nb27CD(F(!o*=`s5)lPTl)} zZ-}dz_}w_QWyIzP^97+Q7X}ha<;h>u4A6Y(WVi#l5UZT4nBCY0A8)cNG6Wunf8pR5 z$of?axdy^Yqc7EJ{uKg`@F8J?#)|FATSUb3(e?^lhYaHsJh`O)r6Fl@N&&;}QDk6f z;%Yo@PcOYshd1E$wck^*zN}osbZs&2Y<nkIzH?unlwqi7hAzR^8l?~pQqvHO-F~-* z%9Gsl{t8}?1le1;qyK}7nBIha=4^LE?))OQg_TuArr8#S<fSSUr_<qPVm@2feRrk= zuV^Z3*^Tl<{TcsRtp@!y_cJc*0d_?rezWFz9*Qix(9h-N*y~kq-n@LeN0(Amkq|uY z!c5c)A3)dV>Ki{cW=FRU7CGz;2)qmjlr*6u7#Mj=Wi-*Xz<cLr4Rrr8U!SmbT=^(n zF4v#z5%T1_RSxHFyKUx~uHBFtTCD+{<#{K*>0HiN`vao^VScjEBF9zr*;QQ{=?+o5 z;nS{i`W?VW4EigADrZDxg0>+>zpt!$y<}wU?#KMmYG#%C<lQNrn=laMWoAf30J;3F z10w^Jm)=>h5KOa^ci~o^W2R$6MeF@mQvV@gE4ge{1x)?xOY+xzb+2!k^JSQHW6fJT zPs?dnm>}CHqP~F}17kt`W#p-LH08wN_P~hn(4EiU;D-|F&l}({5e`;cku6tCtcw$q z0^6^yMk>+8hH92>3K{=G8yg*tA*=Bid3-(M_A*fD*!-*gc;v$b#Na7H9gYw_;CgTF z6%e3<k{J9KKOC38#jLRFv5)r^1hu+5nB29T8g*tl3ERO~j!hoVLL2GjXAqvthAJ)w zgM))6k2TgWgN)|3q{xFkUg8qvXDX4YB)l*CQcb69&WC23v!zQ818QWs&M4>oYo~b> znUiN#s$x1kzTv<PrYc*!4Em22fNA&Nemu9l+^?Jb9l(Lh27<*bdj3i7e2r$&I4J;f zN5JFLt1^>oZ0z&zwgqQ^RG=g3fpp?2rjSf^dj(r7v{k@iA9oh!Ae1IihhnurX(2mZ zz_?6-ZIp(3Fm74;8W{OW5D-9)4lP{Wo1cD&Eb5B!3#G@|Ojc_i2zv?SvPLomRc!6$ zef)Nqc*6DYDm_CM4Gzu{=+oAIkF@oBmsGSE8v+LLjyzER@ecEIBMM<q3}xmJ)tZ-> zl9I9KW}1!tbwBZ06J#Fi?cq$~eYf68%8sI<qKSC*Y`M-(E%<bip#`>tV{O~rem<pH zR+J3yOM;i@ijWpZ4>m(4i2X9V*kLEwPj-y=hshS_i|^MQPN#$A40#2Ja(~+?p8-k| z;6oRfU@AzU8XUX`<_s|y&bim~4Z#|-ytV}ib_b+dq>CGVWn~f^Zi5CLTaS?JPhPL4 zUw5|g(5!tQjrv60=rHx6ep~6G4^?hHMc(n{yMu^k$B_ALzYzUR=TPA1agVI)CAcFI zEpe=E(Op&1uU2XYpafxGNED(uB+%uhG<?4C)>+U^Sxv&5)1ve7w{RTRXwj$TtAsA= zw%1{b(fyHNG>%_GTaq~oUF6=+_i~X+K02P~pLz1`t^omRidUO;1&~Uas)cHMp2V(e zDQG0MJ{tn&7Mj-A8_f!tifVvYbdC3IQ{#G5;>}L0dIy3q587@C6$tgF;ToJkD908u zN1wD%N!s^L$<k1Xbl8aUhuZVX(dFe2CxGDE4t3>jsqSSTACx<1&F@Mfvp<SUFJRl8 z>EQ3R<^|!O6BqlU7!)3U#oOO2blco9nppG8q1i~F6Pr%1FZV!;-8fgk+ie|bbL<&v zXn#>>O^>vA%dm093h$X6DAj_NP;5>>K5$r=7_u>4f)ps8w(+h+9JLOmYIMk7auFbA z24zFB>i29p33q?=W_R)<>#(e_YkS-e83MV@M!4Bh83~K&<gz<M`~G5SBDeU}>-B*` z%0Ze5+nBc*yapredXorTAJ|n%V}5dv2DA0ICuBV3?r;~B!U;%C9uOrp?KBT4%8CJD z7pu~3MxL4q&O_Np)rry<R2dc)Mti}uZGB+d#b>pm-@xtE6O)pXO|w>(z7)i#|B2a! z^a3eZw`-E@%F%$UK=3c`XJth227eYylnSGnFdVl1$}tA)l=*a@Vi?c|KAm|cWf{A) za^=8tA|mp9dPE%VZxUfnCyOG$mygEdCSn0!{8}(3tK?WqU@KwhcD=tvw^j&6L`N5I zHdC}SVtuXuz_eBxX=-{f{rd;o28M*zO!n>ZssIe~se)7@IUXRR;C2*bP5^m*xDanN za^K_NX}(C5m0vq|P51%cfevgA8RVi|<_zj+9X5x_Jv%NveTdUB8ZkriEh*EX<x|^) zRt=lFDmA*Ci&c>d@caS<C9-r2vK|$ooQO*L(O<aAP^E5VxNku(ug-7Aa#E)ZbwD_~ z!4mcMfO%@op$-dv2pMLXt<2CjOVt+{Shquq7rq5!`ehHsPmnE-(`DAWw_E2=ne66# zV+?LrPGsvo_J?yHAHML^o9r9hu=XNUwPnw_kxj$!`_&dbt8fzv95`?h*y$j!jz;@v zw#uUebY4FGF~RsTE)+or2bXa6i;D{ad_l&C&?b$S5g6D;7DeTZJc++rXJ07+#kPvm z-Pe=yyTb%T<?}#OLa0<FXI_F2O3KQIF?%Xtut2&Cs2ATI*#2Iv(1F^*|8gw;D*u}u zwx5d(Po3l*DJqbqE97x6!*v>s$4Rn|?IA(q>{dI~v$O4agnhivqP1pl%O1{5et+pr zUdI09GV5q*ucaKOlsAcu!Npj0^C%hsqn|j0<cq5XUYI#;na;~lYoCK)z}Qd=Q87W4 z-7fAKvELpUjBa~+APH-G1KVYCZLU_E%Lj5CRwO(LkC$s#D3Fmw?zd_J+ZF0w9y(YL zL_EHvC~C^~?gNc{cQz!AADvfTR5A+zQ1)@Tc;&gqF<SlOra;zT)Ivr~(5c!g!)k@z zk3L7H@&GKA9=^NdA1RMlL>+}>y6YXkSDET97Kvz6Bw3G*<}`c|>8Yt{EVBH)F!H5c zGpnlI&5bI$1+^3e)Us#FKeauZrO1T)`(tT`K9Eu_>#F#GqYKS^2WJ@s@8HplH4ZRq zKOZg$SS8Ik!M&+G8?lH*;Bph4{`S@Q^kb=kjCvoECB)#oF#j1%P$b{OU&Z+F4>9wG zOyIE74&W?SpbmWP&uT(@e+hj|>gJwK$f2e2)>|)TpTL@RFTTAXOYk7;R%>lvW<?*( zDAdo-KM}ZSwlJT#cdTDD4K6lXCew4k{`5(On=VuV>5J}SZ7X<u%XSI1PDIfykg-B~ zwxOe;DKMfNBdnygrs4AgvIU|@<rd`KEIblq=U#EL==RqUtr)H=`n%(W^5!pAk*LK# zPk#}^f+G>jlE8qL*`yaSh+gREblOs&5f2%{FB`RM&C<tOqj3u|6O4N>s!{1TqUh+U zh*wQfDSQ6TvM>)JDQf3V?u{ZmFOsOP-2X0fu84_3k?HLv>s0plAX+y8XSu}ing1cp zj3txKs-UQI;Xdd*g|RjB84wRTmRhXhxbO6>kAl@=uVlz8RIh8RNLRqI?sd#HZrvz+ zYdSic_P1I)RchJ>@(L?b*&M*g-w#OK;<vx~_(aBd??T4TE*kfA$RgNqK5Cs)_Z%R5 zR|1@VLQ-w@+m$M*duSZ-aM-@?%%gNRop$e^X*sF!io$rX4H^95grGQdEColU_$|)I z8k?Z;u;d}r*)*k$F)Ak<MF?LFg4bn7C@6nsiyqP;w@SmKSJbc0XN$EA$7f47NUZb4 zWbNt#KpZ5J^%oh`&~1-*$lw*cO}V`43GH{iR9e>=>?eY|e$9d)ezH>MnMj5#?)3>X zQRpu!<{Xd7K4jjmI>B8}EW=UJ)_Pm*zvBbowho5YgP!Ev>o8wk>8qnmo}MQS?JAeD zyG1yx<C$m~D+lxS!2CrsZxYL0yL+_L^EuIst7+Weraa4;>R$OcJ|~wPmtY`zMujvx zrU&J%?g;px@jy}63d?AEJVRl1@1c+4jVp+d8c;*YcpuM9ocyeR79-4hbAQ8VGC2M| zV&r{!P=DR`L^u^ECmuJO6Gt%0UhT-(++tJ3uSKLw2Ed924(Y70{X<;D_lMT&rcfGS z@Q{QsR!B-+#UZg2G7XKvMV8GQ<VP~+3Z-~(z~NIy;-dnB*E-Cd1JhtFzpLx$=k&=R zQFpsKS!!N#x7-V@Rx+ky+e=DU@&meA!HL%2HP;Ir;$xw~sHMiktful?**xF8o{&NJ zo^Qd+c;%xF?<g=(J^?;p3Bq|!V}hlONwXwsLmD?p*ouKiK<E#rdBvYYmHh<3JW2p2 z2Rok54O>{oi^We}HDIp7a78^{+I(ACMLW;nUZL_1p|s37we%10hzJY&J1HW*!@oX0 zIRMI>mGfk07a?yO{d)D+5gl7D+V36#h8Um6jWWB*MClaULrKXzm<aJ7M2YA-VD~<x zifqyu2mkj1m-${m_-C`!9soyH%^!qg^G9~%>ROx!kFYeleC6Lqn&tbRrxS?@A3y3+ z)66($t1Z>xw~nYa=qB7P(qk$8(lBafszV^z2YbgXjQ}lqBG`~;pQ;?Jrcw=h3pm9p z@DHEZX@h117=|i;h*Hh{wo2|6g=6{0e2({l$B>kZ*Dpyboe~vTw<8n`2@4Cu!DRHf zYM9qAytyXaYFixm2O_*rrVZFnb;PQs&2p<C{N(6pF*&(g+ak*Jm+CxyfaEj%X9~*u zyxGYrr#leYZ{Ezl>MAUA<n{e-0e&{fKnOl?E%s0_EKXI>7AsYqOGQaZO}xn7w-45d zfqY-PyVsVK{#mu36(4<|It-S9ijwx)GdY%JVFT%grVnow$*-ZIA(P%q;ef%)Z}ZZ= zWHgI`OaM&7-vRfIsum_rP97;}>D}TV$d+qU&xD89`XhVZZjA*#5WPc;08*L(OeW@? zzzZ}sx)#Oaruwngb8sw&L)~RbYrLP+yQQ+-u=B<{DH5HT+|fs-Y9U|HB10pcO=;p& z<4K0^iy6060(@29CnM+!m@24i8LWkpLCb|_eb>kN+3HlQ23Y3~I>4GBT^S=omR$AP z<w{gvEwbi=7C+cmTG@X9TR(r0Hkcn&wH;YsB;ge~K;N8qKZy&is*(q=)i{M||BQd< z>?7bT-*ts9<;_@Sq@=Dc7O})yw;eM%<3(H2QNaF%C>P#GuJ<-zJacoHC+p$yO^BJt z@sTt>F<vy+O7Wk{5RooESP57~L}?zG=*%C%0kHvcHTY3EJvrk4Vec)YqU_!`&><wH zr6rUukwzL6P>_ZJL0W2PknT=Fq`Mgyy1N^tyGt6RJLWvR?=Rl}`EWj;55Kh@W(^Bw zW<PuOzV{v1b=^RTQxnF8f%?~0DZ>G7Xn&kIkh?&@jp%S03(xQM<D_|e$9N0IWyosz zn?K(7<K^T1xNw5e9>3VfYefVYX<ezp=*xfo2ikj}*5w`iuRntj|2!5#Z*QKl{Z+F2 z-y8gI692c5{y+9YHQ5&j;jI?qOv(T3pnpD5Ms!A^&h`1vcKmxT|9Z4xLLdQso+~#c z`fKa{W%d5HeZb>;bl`OO-|PPGr2KDQ{<mKKb*%kwAN_4A{%0rt|6)HUqLx;GS~PVN zvVnmCBakWUo*)z%btnKAA59HctECm^44l|8m*R?S5Ptph+2JZy?At#N3g9__VnArK z>&nld#|w^(gx1v|>nl^OCm2glhtNNCG0^T#)x%(+GP1Jyb#=k8LjBhxSlGV*=RI)6 z5nqGe;flZ<i4Z&m(_=Iu@$t_UVp1n1?&pADNXfw9$5wV+p@fFg_w;lHlK?`Lf4Ths zd6y^#5R%yMTM*eyxR`|dOS<Vo6RzSED7Lkw=?L{(C0iZg@9AEeGgcW1;qU+LV*YC{ zVxqNy^bk~^?L0+v*y~Y-KwRHlEDHL4chKzVJ_d(4w_-TUii?Z4=nB1jtl0nKl6d^k z?Wan<NN7i2xajC65t61X2nmoyk?*1c@pag2HmkTXrvEd>zn_TXdLvMynf4i2BUbwl z-kk68WeE5h3L<Y21QUnz0WWN7itZ9Y`3uDJkIy;-CRt3B<^5cYSgL@7fAeM{?<6+l zlQ^|-bBjWGfaDWZRgG<eAoBm$&FKOYdv(&5iiGxVvP2Gxv%<gm)>q3D85b9gmX6*{ z<YoBX9Tx!gVO?4y|3CL8CPuATC=OP?TJ2G2zd#-v8w*Ljcmb$7H#)NIF62VX7FT_t z_x4*bv)dY~ovY()Vr28H$v3O{J}D{d9U(}QJSoUYIREzE0S8`j9B>U3$Gs4EEk)D0 z(qA-fNFOo0wz%r<iuMxL--<}z2Jj@V@65wLW|paCyq^IYJN@I;AVi*Tpr;_7;$F*z zrGx|$83k)SLoAxYxe@*B5G<N@e+P4QMg14_&32APM!8>a&X`=d|2)QR|GC;?k@Y|} zMzsP^CH^#a8{Kl$y9cB|7{)7Y&h(+Q;<Fs5y(Q__Syuvm1YBTs_3<@H`z|f_pJ=LJ z@JN3&!<X_p0I~KDD}D)lk8Q#pI|*?UA^1%fCT-@eY1n%s<t#iFGa5=?H$uC+tjl6M zR@!NpG&PhmpAo%E$bI&WAKhnd?Ikl~UwqdJ{y#<sLQYWtp@6n7GYvH}c%vLXB6Sp* zwtD(8zTo&!4i=8SiizRgoh?k4d6<<Dy7OZ0h>}bLg0zhdqY8}$-+#Ir-lxENUTG4s zkLme4T=UKTTH{yYaf_AnZq-!KWhG=gbR+EdDD1NONjgF&@-l*qcqE=Uldjyibrs|Y zDp9aXa-`!UjO5=}oi{M^ueRSc@?<&|YsMr__E|yRNTmbF3#E1X!Migafoo#Se6>Pe zEGiDErt|ASyf)OJKgoB#z{2`mq(%9E_qrY`uq0<Pi9cr{weD>3J)pG{=y^7~n%ok$ znar|l_Wiu@!*nn-G+Sv~4NcTXR_w}Rsc3+O+Sx_!{RqJQ@2G&`y-N~1c+cW}ld6y* zE*00SL_rVFyv!Z@oi2-IbTWMX^XC8nHL`TyA-*{y-6jq~^FVeEdvaT|qQIuVf%z8_ z>_7K7lL*|S;~$FTJ$iZfU1S&D=D}oQ$8)Lh=Y<+u9Z%X@uj7fFuSO7<)%ba+ncgJ+ z__6mv(v||*hgE+b6P}*0!XOa5(1-YcR_xTHU3Bd!DHKn+YAn&mvrydQJs>m((1h{0 z)@ij5Y8|6KGMNhL2r{F=n7(3uD5R8c#TFaN#eYi?{d1)OAXs2<Q{@hy`m38{Q?;jF zYjHzARmO$7KA&lo<`9W_&qD*E5)9U(^r@=)It(XG@ztkPi9!CyU~tKN1Tu}J|0Icd zFJIAUNbAiU9l36AS%U6D!oHoF0T5e!$;pT;*e-Lr^Mb#Ww};^o1N$MZnrciCn8fa% zi@{qA4cP`m4DDzkjgY`=&n;mY`*N6aO<hT634N}@rCGNr5pP!n)j07J*1!)u{;1@) zCWS)-2DW>Si1E6-NtAW)%Zc*0T5sjp*h@2TL?4otT()QgoVSBBn;Z#SE|OTbm)xv! z<JgkOz_y1ierE$Lhhtm1p4R-OshqT3y`u-U%VJIoo-}myU3=hzvmJNW`)}|u!9&k? zv9VWzS>!30Paf+|m&=!K4UiKf)yA6gC(UXd=)Ag~!ruU7CPgn?n^b@{`N3v-klP|3 zjxM9QDB?Es()HjRJ~HQ!T-^mIs+Z7$ki1zMd8(w!)xG#HFu!FkEkvdG*P4y{B=MTB zLU((x3U_`bj(Z*lzm9J!H~f?ED^a%lIv0?IO^IW_j>zg*d4BFxEBa2QCD}~Nw6$T^ z?h%gRFV`yg$2FnlVKb;~5?Y(Jym&$G3W#W*hoZ7M{j|gxnJ}~W9V(6GxSSy>{sNh* zV2_QhHw+lRNRLz0OuC8cvG6xr?q9YkMQ8MX_n=i_ar_Lj*dU3PyFJ|Cb}2$8v@ZiI zDVa)Vdivvhmu`GNF<rSZZjiOuauRm_b>p{I@HbjC>J>1s|LUqu{7i{kzx612ihE;n z%0eIl=i9T>?0ko}qK9|G?EPoK@5!h?T8ATH7L|xdzj-4~k^e?D4nINU{O#^^Z4fu} z{<O((+9Pa1>gxy@0fF4DV`<j*_I6pVu8zKu5nZ)KG@C_ZK@3B{hUe_sVZL@FSieBF z;Kz>Wuk2*&dIct?{5mld&@1k2{o0Iy8kIb+=5toLrW0kk*baS=^HpZ!cI4$!UV(HS zKK%Mb@NECoI<Qb6-PQGSSBlH)YKGy}0-tunw~Pe>m(>!Yb06<qz`B<`E9Jr{WlPab zV|uP1h^vF>nBdN5y%efhZM8Lh^o@K9tq>%C-A&U$hS)7Bsj8S@Ew{=ziI2F>PWATi z{#LTn=&!W%p_6E)<@~ij&bgxORipcS@$@*-<-PptU-X5T%sDAQq4_`n8~nbU9<r0g zG|}Q=-WdSDU5woE!)eU{h>WPe02Ni)hU37(ovCFVVny&PpsOJz8RwmhOV!S$t!?>N zy+g9ajgy?U!P+G#{O*!VJ1{g5i)&{}t0a3FlLcdUV)U@1KRl$K5(&h&5Z>?=iTjgH z$5q(QqLU7q222eFw1i*jntM#hdRP1Vns_M-AakNF5aCm32fd=?N_jY2p_s_@NcOgj z#XO^W9dU6WN*l?0|Bzg|l>5T(cJGzb+*$ousguY=a|*n|me}PX?kUNLv=ha!2pr}9 zbi->eE{GcKUj{Mt^>$ohBHcbk7{*(<d<hw9ju%lk7nf8SR6=Eu7yGj>2&?brumjP4 zlJ9)SC}V4Tpg4a-Nr*1ERKAidZMfmpZ2A)W>JyEGuKNW$8Hc-G8>^&b_XMoiLE4@2 zO`Xp4yr&M?QsHp-SI%MgYy-a=vnu_?=P)fkdTJaU!jZa9hu(JWXxoX@mB(8^#h>Wo zaT3rz<jUXmd>_Wt$?}ej=OC9UJ2oHck&=E3v`*(|%gLL{rVwSH%&nP4@#e@58ttWO zDJir{`z>;lVB49U){*YIra+mUO*sp1Jf=+Iam%DsddnFp?Ap3QypA#`v^A7^YSFIu z7Mhr8J{`gBHAIXM_MB%EGS}dsCH4kLRi*-djNaB#xnk}1HVI6()hB=_!;}rtG3je9 zpsqm1cf71p>%M~s%P$&%pp3Cnw?)T9GuX2+l1c_jP_wZ3)mWqumj%~Qpa7j8>XB56 zWpv#(J~V9ZqHDfP^AW(A8N_I!jgQ}i1f--8OjP$Wvf;^&)mSAdBqq)c*9<0m<&7Ga za^ya|(iRx;t=EOb5th`h-8o+NwPPhUa9d5WtY{hJBA$_f_z%a73eCpUYMBWQ=lN+4 zxPF2%psge`gap=kge=nmv5R7>gI7+=4}5y5a$09E991Dw{GMN;^SC-0(p>{|ytvBb zjkh~k#GNIBHLqOe<;g_sDl|FQ#M>?&_nHTBVkvdgZSwGhX^0GpHvon)9q*}@3geX2 z`H)^|!eX}b<2o-UQX-sy-}8>~I2qf&k6@<31;NO8LS2n^qP7tBg#3M-=>+Z#&~uB& z-d_N3!xH_CbhWT?E4-cfY@~D5{th~|Vv^>W;ORDA4e3w2D(VrIu>0DhGc#S3l&RU9 zkx2lY?;fxnFx}CZnT|v;QBv)$bZ)K@q(AgnioWl2n=X}0#FED$L3hPIky(|cF$w65 zWK`lF4k6kSbHB3WZzaT`GnIRoZEFh*e2@I#*6Vc{(@~&elK*xqQ|3c362d&eYe%c# zgJh&9)o2qTu(t_!=6Dzinx#4ew{tIfuD8JPadB5XE%K>-f+r^`Fcirz=$>!J#;caU zOi@3_GiS!}tfq%!C7(StGpqiDmCWZ=U;;mnV-qbT>bD%NRMjZ}E%6lr@ACmqL1X{* zwaGoz!%r?skCT%L1@6@kK~q{Hbl7A3#r>iR6*L^cpRcf*ra0YcJTY<()EdCaIS=do zLBUwGjyS#8)~c$<+oS7eX)DR?p>1%SYVgR}K35O8<yl>1<9XA2!YAyhIA3TL2U%&$ zD&JNcK6N2i$)SfA*&Ap7>GGP7K}>&kythZsO!opC+2YX`op*|QgJJyTi!#!xAFd1H zxw0~0EF&Xhj*xz&1;41t&~KFwW=zGODnBbhrz`~-duTX?kPZAj24Bww1XU}uY5Hk; z-gY7xHc}8ejCN0(3V?*Fmaml8Sm?uZBOfl4@LwuCZ@tIdDmR6NGSYtC=L`?TR;S82 zRbDnPt(SNKb)29xl+MTal~UbyMD94*;rnr=`6^QMSYdL(VuXX`?4Wd?NB5_g0eCSp zhRbBr1lH?tu`Ns=lcjbFxtCityu7j=h@$CLJC$Z$y*mCJY1K6Mfz7m9jt!^xGz1mW zE<;5RaTr*yeyC}_8#A=CUGVd!dGwrvtuW+({s8aLt>Jhtr89DJy12?q$&)kky8w|K ze~-jf(UMRG_FTH$uP-nCvvdZNYBD-HBw(-}m%32zj%WSwp!K!2PE~T4KBA`IEGZZ9 zjOz}AVDFe_5^R#!<**iT5gzVKw>CzX+&teJI|XUXJMB-oXW#7pR8Wi`I%u{Wv*&Ob zGlChEwp>t6R@u-uU0<NWCKr!y;VN=mNj57h`jfF#Ql92gdsvbWkIoXMumB5DW(`bS zX+|uE2velMw>D=+xQwP>tT23kDNye$nZ2k?0t5gd0Dn}jnaN!C<I^R|f$tigEb?a? z*2mrVaY!gn!4s=9quHUytKkdf+AcdbYHB>GcyVq0^IZ``Wzxd#!Z9z4p0CCVp-mAa z2yA#v%FJAkf8$#&OtOkc*2z2qYRH8!`=5hzx9i>Eg>ec5?Ds7$iH*?@C}l`O)nx!0 z3-TfK7$8@uhi~=iG*=0q6dG4i`!H0>q@(*9zTrZ;^;ArzH3O)H6XMpNQU$BCTko!M zLf61@57iM*H{gY<{CUdd?c(oFm}zwIGKfTOf3sE7_V(zy-KU1aBa3dD`H7xAb9xHo zrk{_i^*l4ef$!|hh+2dvaqIx7^41UK{G;kDANmtNMjZt%V(afs$%R6mk_mm}NQ*~I z6L6Rd64%#{%3^&v_@a%)rHroac^oA79gur)thrILl|Q+=3$*EJ(saI|!YQP4S)VRV z+-Q!|6}p+h#M9k;HO(~QVYKn70p8A_+Ff&Br@<qacGRuD8yE#mzp4D(B(-o#TaZ7q zoc@&0bNuE_jb7XEO2BC=cp_K&a5VJT_+3QnXAfDQDF_AEZcWxxwsfFp3^v#y#YC0( z0_QOh))N74?3W4IF}{m$TkqYA1lbJL85VXAOslUI^A&35k^yn-S~(=v@qGY{Y7y4= z?WM^{Z0gqbD_q}D<STgH4~`E?BvFBAN3$0Yar2SFIEJxf8Eda@ezwIKCiU^WZ>o|H z=R?vkGe`NWZNrUzs=bu7G?`;t+lGlPLJ)XAXiBaATYzSDKX{@<DVx=GCqSBTyo0o0 zv+tw@l@gjQZO^J?1WyByQxQ$u%#+-W3}-*V7x!(hRKhtP&vUCRi|4UomTo>*dU;>M zvs-@jOOx;c`H%+SEX^Q~<w8Do9BJ}|m56L{t+L}?3<Tl3UV<+kbTz(25`q?L(mm&3 zGhG4>zNasg9BKxF^b^~&q0eH)bAmwW_-*s<xWDK!HoqmAk7`~(N{FJ^4+`0rl+<3j zjcmZo<lk?P$u0UUPaICD%k|Co+-6oIvU_Yr>SX(ZKgr9eXc65f?=cWisgo9D)DZfl z@_OF&^TibqQk7b%-W)?I;wH@<+8<$T#lGswJ6Ly|8)<G-N`zESJB-8dY~nPPc%{K` zWFTIX1pI1716zYHY^+$kne)ud%*_N-<Iu^-NX|@V1w6X$3r)_}0}~@8F#yT;(ai3c zeF)cu?n%0<H!c~%(q?o_%yZ2beFt<lm)d-8r5nUf53B4ajOxp$pH3k9hf7G14-vt` z!ckC|Nv&0?>Ua#ka|L;y`Rzk<p)dhSn)lL?*O140;e=;3zX+uYll#qaa!dxt3-ExU z)PjN*F*8voHkWl>zd$-=?b3;Px9gje)mEY6q|F%Q;?^*n1-RSd;MIQEVS(&rRMN?v zmozubQbSNnV~1=Z41G}MI~pR7|6gf<ZASe9<IcccSsv|?ce2TCw-VjC_xs07p^B}Z zfd=J!Q>9AbwOU`+d*tNQLllH@>pMwsg_gRyXaQ_3l{-S;4xP=sW$UrdPxh7@*9IY& z)RKAgxjjBEo5H5l{EM{tlHM0DTf3hzaI9TwSqr^&&#OyDOn=R_`NNzrxk|zCLz6)u zF3qFM1W^>#E{}1fh^07X#z4ipZk#VsA3RUL6jhhAm+_ri?p`*(6IO%hTK)MDncYmR zdlRo*q3}7H9%~11l|<n2GeNyMA-nVV?ig)YXcIPwuhZY$p|;7l7o9yFx@{G7+R<mu zz2k!VH#<r*GHjV53%@@-@!VTJ3R`hK+ojRDao^gUIc!?amc~}1!KA+v!HQoD?g2%} z%gE=DBwv-i$EBYJ;H8<Y`okV&^VDDD&KJ@|QXc`~1SP{vbmS3*<SOxFPkPf`7-A#s zxj*Y+4SpXLbNQh-ZgaL*_`nCh$4L=2TYdQ5PfP`eK9kbrj@ca2%8JP$?UjCMw-QV1 zbzAsQI}pwAjpl*z$&%yAFMI0|lXNd=jKyA^T(V~tv5tE(rTdDbsPODnW{p~#0>6K- zEIa9k>CeLA<^DDk%K%BByTM%Ii=Caa;-LFOcWtof^BFJSDIyHBC;Of22Yl)0?m5S6 z=hMq~V#7kW0u%!7s^J}cXcHR1O6RZJbCDR!@VV~wJ^pPzf_spwk*QZ0|3m6-XQrSK z!oeW_dt|A(v2UO5q+60s6|9q|S*nK4bgo>)Ja=ZtXQf$c3Nl^FBBYpUoj$wy{e*}p zWtm7R41#W5qvG+y%k9)UUt7?~B$V~4C;4y;V5qpCm@aag&82A8n7(z$%C7GEs30pR z2L<$cE@HI6ni4GPWa$=tv1{<!bMh}E{RH(Vw7`-60uf-fs>Ci=o2NsPqVXLM!PY_G z+w-d9YQ6{AyVW+gOsM;P+Gan#rjfCck@HhRnH~(!pATnTrQ>_nX{EA-DerTekH+S? zjn7{1E-iYQKM`E8SSYGBf*m8D`N3PVG(7p~fnHKHW4Jy<#q1W6YqhsR?Kr%qq;ufn zC9&4l^%p;%i=z~Bo%ndGJ-W@IMco@xpSZ69$=f&8meZpK2S~)jfml52J^j)3Rfe|; zs!B?fbs4&}S9JoyKe-%;O?_8dn%zD!cHg~}3Gld)$&`(^(&qpLJERjVMVu1(M9~C| zIZVqFW%INiHk^X3Z{B)&{<2>zQzC#&*U(JzuEg|dy(f8Pu)g-huuVg=P7mByEjb-R z6b?%C#iM5UU7;v8NcTNSQ=$48s?fOpB~pd#;QhF1D>F$fa#~Jg>j{19M6y*=5+(c= z=^44!G`pNNGC48j^?Y+$B=@kem-_^m1w|^dxo4eFrzMnG^L3N_?St3XYk%^b-DJmR zw_dyM3KX112@cAr3;LtMTCQNxv5`7kqGm>mLQ=vk`~LlhX8&yFEtxQ)aD?6h_2qI^ zZS4bsNOD{oq{qX2Cd~a#J@AS318KnA@8$6RkY^6fF{-P<1w^oD_kyCkq|5PXs{K}I zOI1;f=R$=~D6P)93nJ;x2*4DUB=o#-2{UNYrdjt7fz)*Z{n3cN#tsYLl332v`PnHT z*G^_<HKkxvEJ#a7Q0Bp4mEwCZh7(@iUASE|9D(0{w0?Q##qVy~>P&v-RHgU)V?n%( z$%&u2(+D9=wmI7Vywm$?w!vh+%yaUT^IF*g4mM40rO=D6gZa`W&&iJ{1WWK0%(X}W zvkDayzS|NVSrNaF`GM4P3_-B%29aCLIg#PNj+{hvH$Y^+jSqUbcOBDqT6kyOblxJw zl;f7$P}kO*e#LOGP|ufB5j87<JcF=RJ-u9zk4v8NKyA@`y)ImfVr06W%@Rp9`<v}{ zZtpPT`ZV6<&=vtvo*sncjpP;?3Ac0Y6SYse$|l<F=}}JRrNFx83l961-Exm|P3UrU zB(B*E2`EFP<^(TbQ{2UiRQxc?&Gl@Uqca#z)1GK>m=A`XcCBZ+X&+8j3J)e#%9K;M z2VVYJ6x^Os+C#lnelqYgrZyvmFy&<uAwZWdII*B3oZpW@ubd0AE21ki+T)$XxFV^w zhF-M<s1VlJcH~FxMz67HP0Uk8&=+ghCeq8dNR|UgEz_G@n#-s-Cl@m*oxvCKf!A_( zn}edV(Veb?KmSN-=MakC^ic)0j$;P2_TJ`>itC<EA?B9ZZ3qAuKAe~zxLXp4ci~>w zv0iQ>GK1tI7NF+ioAC}z9*-7Xk=rXa1rGNlrJqx?GLkQ`k)OW>BAni@lYo#S#!z3; zQwa9T%(l&)^VM_c5$z6?if>E-<C~nke5QPA1D=B2nLoW;l2Ua4p!>V)gFk>C4`XZF z%|;PAdWeXF;HvRfgk>m@l>rh{ip~)r!@Wk*OixWj4?r5x_?eLm=`2zZQ=I+X6<+t1 z9!+%g9-g2&cZC}LOvA#D$kcZQZw$>9MZd|Xgx`f`*_4Sme)PaZKdoOc3F^!Y%yn4E zw|%}`bI{0IEEv;qoj=zqa+0z|!)5|x)sW$g#W_lz)AlB*PAeq+_lIorU&dP&AEagp zWuZxH&%W0_JDNgtVPs>=Mklb2lh*PSwY>S<a91%JdQMA6r>wu~lFk>3h#g$SmLic$ z6!%K2IPOc>m1LN@a=aCd``6W$o8d<G>#lxleE)I=@`@{D<YGhIjcXemM8}uF>PmH` z@qPtXc&NXj5cE|33Yu0*usI!b-8s1d?P|t-R<sEO7oRvJIns-!|G<wnTgk}u?Va)W zcIcfbmd$3rIB)p%vnifchk9R7l=QV%KB9Dh(S{>7#5!WW_RusDA;Wsv!a&;3IB3#* zp9^iZ`9Vg1k7$DrEK?!1HWsjs5J|x`U8a}g3GEko_${i21p;~+=k1mo%bPQt(Wxk$ zmmw+av|OnDgen12cxsbt{j#0(!U4r{YA{YPz^aZP;c0F06M_G}n^!dxE>dUg2@$kz zjdGUtQ8rzIr7Kr$*aCvf4KRe2XdGSjGaUVTWqR<@DrzY#t_Pbrm1stf<^e^}(Ns2! z7}hFO2PB&(8lCtCD4i3>lh8fHy@6^|UnDh~+%i5LS5oKgeJnk5Q&U>%AqCdy53^!k zH4ND%j1x?umnQyfPq;j<mK0LrSDbd{I@xt7+ohQ!NZ#}?G<?(u0YWEMW;~&4RDzjl zALW^5bEtCF!Md`__{Y&G3Jk~X8Oh3``qSx=ZKX`CIl$@MUJ-XA(TaIc-~cUMdX06g z-_F>e(Rgnv3??T;+jqFJwQi4QR|*YGUV1gbIb5%Ed!NnsZNZj34rxNo<b&^eqj3sg z{cc^UlohDjf6RQx?A*#Nf%L+e{MW8J8xMAkvhW9%=bg@{a?@98q(yk%>Y{h|qqlbh z>u9zT&;(Q4oT-|?eTzMLv9h{POKaEusMRZ9bzd~$2YU&+$K=eJ;TQW8s90SeI6M;H z)H=PLam(ob0)3`c<{B#w$YxkAYG6PS#ELX5JCt9srt6lwXEG9%A1Xe-Gcq<tFMJY+ zDa~ELuB&1`v)UPCIysOF=@&U}cD*EA>Z&>qSx+u)t$=qL?9cpU;$UL>vbcx2HI75> ziC2CqlkHPWzHl;M_|5pVuT-a5ex^`JIKRo*7)Il~NyYg!#vsb=az6(NwaDpx_X9gn z3(Lz#dg+0_V0T)5b|xAVU&pRf5n2LdHJ6{hY8g)wld@ALWVWlVkqrq0YyCS<&1`fU zrozGyv)tam!&UG}1#bDRp5f#!&iIyzHcWB6)V5Nm1DwB-Qg^b9@Zd&`BSpco#KNC> z8@4i`#PlnzGT76;b5Z6)O{ClHpo!_&yXDxJtT8~~NYr&dB)&_l*Q*vcCB5Vm&)aH> z%sWv<wrA+ndM|*JlGWcFJi4lJQ<}FoqECz-{beKICBPSp=o@vtd(F<s51-PNJJeg_ z;;b+|`i=(_Mvg;v0dZ?4zG<)J{ha=3W_kBiJ&@^qiJy(5J-cYkvip6aaVrj)P`K~) zU`1t*8cY23B!g7b&2D9v+aY2AkS-1+V*4z^RKVo(j!ofkQ84+(9@AdAUAF-<fqV&? zdf%|<TROV#RoKwzdA=NdozgvOc(#pm2p=Xj`>5JH)a@S5q#)DP;L-{QJbjv_8xKL- zk)PHr*H=QhNAay9Ku-RWE0<Qfx8ObvU<xQ8p+rtk@>X+7++*d(-d+<g@97w2fqNcR zc=i=JX7u6^y!X_{qs9T&tv@!U-4vM3G39cd=$u$Q^WjxO*dn4}yy^*iyK6&vv*S9B z$1gg-gw+elv9l$F#LUWYTTH|Vd{xwW&}6-OqETsFKdT0dbJ{&K6HupUkz}!)tI4Jm zzRBOsjw|zm>uA<G63Vsg3P|EHkbq_sI<AhR@6L1^jRTIRTw57LfC`~hB&ErWsj{jD z^>ZlK{Cdt%DIx*Q*!bXVg`R3|{+tr`*DKRW3uCIn0?jB^1TBOwVyadyzI_Ce)hjXW zI$o<5duGcX88hL3XQ{P3K<vhI)gGh(L6~*v#vNb)M517&t`L}PC12aO=9Fj)Fv2vz zVEIAK3$>5YQX=PF>Dx70rSVcOr3W{SBT4SNlb?#8HeWY?fA(r(pk=4lD~HPXmwKP= z3mLXUmeOWv1<}*FC+*ZFzqmmY#pHl$TdB(A%St6Dxy}Yi4;o#*t%<`Up`j^<>1lqV zCTS23Rkn@?J9dKT0%B>)39`1^IbrDJ2}iv9E(j5gKLCgodH)n3w<o5~&3C@fFRr2U zcKF0Xf>7j$OEU1otJ3+H(@|$==;xdt77!|+G2oiwKz!Ne_uU~VPqWXD;?S1_@It<) zq~t)VYbB_P)wqDvQHCGt#V4iWKb-o=BSE1QLd{Ii@p6fhYPR2QY!E{FYl79u^(yV8 z=&dw2o(sFCxSmlOhFw6I${o+2LY9g`V8J?+J39qc2ff{)8z15Nl#A{^JwnZ*Lc_zt za*^Do8NsdY-I@({W7dS@zoQ_n2+a$>H~J4J2do#ZGGNfVLGn$E!a>dr$x-ks$xkIi z-+2LgwqGBSK=E#VHYZ(}!v(iPrlYXd6>CQK!j2rvNjHkV@5hl)-CT8Dcx1`i#7zoU z@_FM}Zm|3d=uTnfC)~nJ<Zx^6lFW>kqZWd45B2wVQ$Hd%RWSCc6@Q9l#7J9zu0HBn z#*X%yx&)NBI!;dN(}eHth|)y?G3Jr^XOW-%P!hjxbm=O6{=BlWABa&Ca+Ej@-3HXR zFZG`l^o!E0^5MBIN%@DCdfX1B!I2<Z##eBK90vG;RCBLM;6Ufj^>r{b2%cpHTB&v6 zTi!nG`h|V4Ne4H^23Mo3yMKm)wH;U5ZxT7Kw`zWGq=GHSjMiUe@mgx;=SjcR-{L*D zRBLTMe|VptqhT^lIpC>$v9Idc(sI_39UAQ=GTRp3-<tK~h1A1gXX!S(mm9b`=H5-6 z;1;vYd_{$*3d|vN*^%4;45w$6=3bp7)N=R@+1(UY`BSb|73COpaa#(ZSMNXwP`ow_ zQ1S(d0{-5F(vq7sYAh-?nYcp$-I|OK!#*Ia0hZx>-m9~a>L~xpp46@1`K@(oVPT=! z=C1-(P5cEjq`-FAm+eVe8_k)9Vi}m-nd9o0V5-`=J^kVwrqZSNvMM66;vaOZKWl0t z?Ji~4!mdII!}34#%XP>j6oSq!rEVRI&34w9l1QuQ`;ti6-v72AnT(KF-<23WKk_+$ zMnF&uJCE0u%WnMhPzZ6YBdChouXuIm#8+s$LSPVcHpS_>U^6bvZ4X{KAe7liBIR@I zflgFHPs~^>`nG3`68`K?%#jZqe$cs|Y$a1DZM}&RnzLswHkrt8Kb!5feiEbd>@}|0 z1qP@bB2umgcz#`4-PUGqgiku27fivk$cT0AC@dGwvYiWW-TqaRRC5uuL93#B`V+3! zh=b1i7z|(u2Bqej7+t&dRA<7HtnXQvSxm3To`@G}YiiQ-vxV*Z^P6r2gx}xbWEl@8 zp{l)8oBWjY#t^nbJ2V$!SWDTQudTHqT&@`^*dFAQ^k97bBv|2n&ci)wp&B41|0jE~ z(Fs@<oIa^IX+&TM^)|4lLBFhhoT;pHItU_##aiKua5J!VkKWD0t*0~~4GlFGj^af= zqW!@Tt+{&O<?-Ij>rRplZ?Fnr=*=~n=jMfzHu111e)wW&lEIfR<)CtVPtGPSX=Huo z2KS8W(f!k!>%Y9uXECN?gG?@cdr@>TAj|%1s+$?fJHL`lg(J1~?VD~fP5IZ;qoWSn zK-LGLGH}2H$iH^6giIi&)3-q}-n~TTe5rG~Cm0-A{ntwKMraEZHb(9Bk}5lr33&0A zU3su0dM1{Is34DpE+!^MxnS_JgK3BD8@X5am(Y-iC@Gf`7l40n&C6pwI>0W+=9~KS z*VU>UET2)GV3cqf==ZogqcoeDt&GrA@eND)WaSGIsFv;-jaX5cgJGL@rXB6ltwekK zYD4wFPjIsYZ(SQRXg$?t{G0l?{V=j;=luh!?#Nplc&GCd6nkz+%!lNuVXTC`SoP&x zXu5}RMhYH6n%?f4x#(2nib}CUzqDFd7Ivn*Mwi`{7EVxM>Af)9=P&om{zIvAqaD|} zvXiHc*qgz^uijZ!K<H(aW`SC1?!<)aTJdGF!m{aXR>7r?>u7}>FClUAZATjf3A8ud zgU#!Tj6u%#@Sa!~wy(;ssFS^8Z|q6WFN!TBU$+$*IcAb>UixK3>k^1>x93Zj$Db{G zt-L<}*`lh_Q`9Ai*^(zuF>glH%VJtpgKTCj^%Ct}0&qa!{Q<e0H#u=}Rb~p!;axV> z@(XHt7|`nCjpW)(@6MMp@R%(GhX$a-S39N6dcx~Fs3wHkGc!&jSyb#ZpxiD)l&=$# zxXtn!(_PZ<n_Map2TTA5u_rMKVIv38-WX23pE!K^Zn898yi@v$+^NoLs=Zvi43a~> zfc-rof%Z-ZwSc!Ci2vi*b@P*~YLR*AH#SnMk~Jenf+$?d-?BHi7x8Hby?+1-luW!} zm)qFS={)9qqeko1>QDMkNt)G@Ntk0h<q5p(JE=@ZcLPvN|E&dJaKN`E<FaA<sQCeJ zhQrDT2bcSp;|ULo6N>C+U28&u1<FK!6qYupPFc^qlzMVMXx-V0M=#gx>Nu%}l5W=q zr9dW_xS3_ngPb$%crKnhjWu1%#{Q59#SB6aQ$3o}@|1%+pS(EcUAc5x9tMyk4~l)a z!?VGchhD-81U<UX%jA_-61SEz;&rcUoy~VIrv@<@xw2bII7RQa&0SX%6t;h0(VhVX zzp<a}!bI<XMYlNjGdJw+0%8XeXvq6AKzN*d{t+PKYg?;X<kdt9KnUn`<ar_f4>afU zsRD9duG@zqMuIy%!3bhYCGBqmG3Uj|`m@yzoh;y=j@+9*%%qdQebgf4-)e|}6$$D4 zyiOF&<xDIEaAI;v?%#wkEoUpD905f$;=>%YrRn$|Yw)-aODMd34!cDyRgKC=D&-cl zh%UU+3x<SZri(GLvEo|1Lzu<5n0BpKW3AiQ#Icv}wG>mKePXgk#V|g_dLgBTgG(<A zT4Nbk07q~(J|&qK(`~&=fWPKXcbF*{hGn$I&MRdpVHFEFifV-_6Ctg|pDhXGk-TT< zFUs3nc=t(w0y0C<uPR5ateHREn5~%+6yeu2_@^?hEX>S1zx#y-*-(^SiuZDVg2!_T zttRos$<X)%A6=b2W+)qcx}#U;Po>u<=0^f^T)y!fOl@zw8Sb9XWZ3(T4#|6o@ABj# zyv6zXq%5}3r`Ro(2Hh5SbP7RN4W<tq@&yzr=|62<S3H^^L#%?B(GO3*P4e&0Sa*j? zMo1|tD}TJcHhI2?(#SZxv>eZVEn<N3S=b~mC~VU2a`{mS%dHM}S{Sq}f1)+;9wn{m zh?ZVC6Yg!>CA&F@0g1L{!2<cXliJ+YrGf+AlYnw8S7SxA_y(b_=Ra~s^&5>*e=Yit zlR5_&({}!%63JU?ZjgNUghtv(>YX^i@e;=eP^<54z+Yq)tXEw8%q3@|SWoLss4(kq z>g|cgh;`-B>r-rqGPrG*n%x*I=jvY3@@Q6DNH*VW^W~=$7v&tb+%j(q#Lg+vUzsF` zEPlGrL;<+=gT2G;fb0>W2Vd~@aLOA=a=s!wYYO-`HPF=87p1RVwhp$QQ6vRuu1`_b zj$g4@aeEBg=erhcY{lZId)<KBgsUOf)oZnfGjh|PodhX_ld|cEj;nHV-reZW1py!! z@^ObxjaHRM#wT$Z@t1o_jQA*^DOq#3fY=_?62URx7jeof#+Fu5*L0z|nA^W`52vkp zF-Ar&TAO#sTsL=GHI%!l{#+-&o=Smym}Pv1y#Ef^8|3GK$x9Dm8sxmco()y=Y{`wV z)h@9Sncp7H%xE<1pM-e20!^1Bj<8#o*>wc7h_vZh_aeWAjT4P0Hh3;V=4!1Y<;`Bw zA%RT5Cq@~Kipl7_eWqfaf#0SkAcsq-U-jTRa-<COY5Y-d_rKu3;6%PU(2<f7$VFR5 zMP^WMI%~`e{Qa92GD59=G#n-20v#Gb_jz)dSo*<d*_F?FO2fuCUIG=HGEW5&6&d%n zgf|7(DVzpSuYgP66_|N#U0a(2Eyx1YtOC9st>CRi(>}tDhX_Vml}Nf+=@c0R=EhEF z)STJc3-sllGBKHj4h{*rNO0&-_Di20<9WDtvaa^EWv#u8yz=&Wn{R7qq|nbg(x~7y z98~H8zo{}?b{*>6yiFnkkXN#g-N-F2U}~}jsv69PQ{Us_<m>A%Jl%G|7YikKcZkEi zgO(HXylMNVCXt@EIZIg-G`+naDr)T?sJ+ErBRgk#?Q2AA5q$Kl{k_^+oXmUwJ8m<B zf?AImh<QJDle+7hncXy{q3FK-Vn-=#_bVopm`&4I=FKWIEeD5EIrEZzG0}_*)veqJ z!Ij+ETy^0yN%fMt6|6U}cq4kWJp-trHgV~=<ZS#{Df~OW(W1G87=RoK)*C`q)dAxu zK+^}mX5Q3ISr=f#4p!AjQP5!16pw;(|B1Qv4+BiV>Pw1@G)Cf9Ca>+`NF_#3kbH{J zTO&e;ZDoC5A;X3@CPOIO5#OT;RG)&zd{tD&O(!G`bCqDzlapJf4M%xtkyc#zGCySk za&OXID!(3%CePJa9yZ78o*jyQzv^6_C=k+o?Nw7YT$k`e&Q6T6ls)Cr)j6GLuE}hC z&IV=_){x~-m#sE~q8HZUjsG{){P7XsN?(D>ew6rBEY`twm+rXr71rP4EV4v`n@feX zBu|MM6?!%YlbKT9dTH`l=MbP^QA){pxURH$LYA5WUY!Gq8RE%&pPZg6R+Sz2FZ-V= zd9@=$uRwLb$BsK}H3wKYyBvqp?vV(Ieyg}PoJ?UU4HYjN`DSic4JduLvgDfkOX%?L z@$f`Fn#%3-$6}yN=r0cTD2s;-@!5`tJ*$ZvTN-9|cIf>r&RD#z2LpeHfY(<g*LxIh z1OFOB-XT6q$nOYE<#j$O{u=g#+RaK6`RtCYKK^DvD~8|5h)3D{hi+3U7KoHIk^Acm zqiAX_o>2#fXA?|<?CR-eP7bY^>bLqHGZ0T+;i%%j!L>eQA0M~!S5Gk5Fx{}vB12h2 zRnJ5rwgb<>wF3~PM52tU^SmdUt97bPTVsvY_Zym#eKoBntuKx+m?o?pZ^0kH$yI6E zHxktV`_=zOUN)X}gwDKrB$l9*=#KE68Mw2dVhEC%SAyt`Aa+3P<NWUr26)am!0NRa ziI<V>w#<mzU<QIK&d;cBtW<Ay*SxRu+;1f{BHhi#a!8GENS-UQ6U|haQ5-B)tHc+5 z-p&+Vq}gA!W{bpjhL1|8kFU|OAPz90b3-QlQLxEiF~5nSXW&JJzTd$*&9};c+#!!F z8xz~;f#^#fo><5<*fA;pQ%EO)KFG!yRl?)HV;T_$W`p8;5s?o9HGc;&I`)||vb3va zW`3Es@nFR!mRqfraDn!1gy!UJ?vqN3hj!G%yo-amt5`ydE&_#SF;uTv<4ovNkxYZ% z`5dnAJic7<7ar!h(~%hb5;YW|ql<k-<`JUcA;ZUIBA>gKb=phAoXgVP-7`h#jzY^w zS1<4i&`#86h%Q0#?Rn&m|9yF5KH}~C<cmX4yeq~ynO`w+1c*=>Is#$u6V^Rwdd*l( zdM!%KIR19JaBvc@WeHtYqHz~U@1je$WX2CiSO%()3TXT+P7}z3NZ78pzXt)zii+UQ zo{4fp6PF)r!nY8;bgcG3&1#5C1nY0>Vw<BC1kFm<`ndOPRY`SN8Fh8<`Tc}NsmcF6 zqQAz)9}lc$yg!X|)!D(9TGLf}U*N5Hynq}~4p3J?{`J^Wa#3d((0~6xO6qePoO)SK zAc`Gb+90ol+Kl3Tx#S_o(K;Jta&o%kgGxEd8YjG6$>8Cl@p3<RI2QQnd-nVgYtpfa zA&z4`=&&FsN26)-u0`Vr`knSlZ3LrfKyRQ{7ZO4uQwU7UzyOAT%ZdLBd0do#P!w#4 zd<2G+r#%1$%@Zf&<na&N4i6?(si@fd1oC(@Tm8HST_iH4y1M1TN*xyn93Sr=%=LHd z1DyA+rv!I~2ZiNjiIVp~?4P5(tW0H^UC)N&)3R>=z>^hjbNNivhJs3IikiL$E~Gri z$9j$);yb#6@0IPt=(SUazD75gz!59sUpqXO;glPotYh}3Zc4%XTh#wy?fju%5%hI( z(z2Xw$e-IrEEF(a?Rc}4<q`(6CRD_5?`XTWk-r+#(HXKs#o34QnETr2JGD@rd+B-| zxSYQWQ~nVhU10Qc6X=kH&`ma!rY2I5DPP5@@XG&kF|5ZMApUcEcF=ZLyg5-0n0x~3 zkm$H^D14%QX&OS!hKA@PuYi{I{>xwTqyO3gWuyq_cuj-P90~=h&9^bUZ7!j8LP7%c zf%MJ{cXn(O4Dd&3#%go*ey#*hDq>=D*F;wg_amRioe050^=HK}m~wc0DM;}d{!13- zf#x2N<pYEcmqOsHH@FnTQn%H0=lwrF4$$ln&oC|#tyNl1qw(Ae$9;tu+o23U-%}@t zl{7W6vPOHol}TiMPC#I37c$Vz0SEH0%nY!ulLya_4{9saf9r>W{>34AiVLJjkjjd1 zi@`395J_#G`d_Z+%BE)tvVIbZwN^#b1-bz%-JY<O!6nNV41DU<A0V=wlVB7^!ijhM zZ(eBei@!){)8cyv4c*W69NMSyWkPX5#LXv)umqyw|C$IJKEQ0fTxeBOo5Y)<=A1lL zvT~Piip>O0i8RA?#L4#F^ucG(M?*4Q!oU-?)-}$1rxYr+B~F~KOQ(105)Cc~Gk}nF zwb}RpbjW5w=%KFR&?jGDz>9vu9Vz&x#%w+U5MrWPf_a|8ybqs9ha2eie%o(TVxq;A z#t-fBP8F;jj~gV9>B1#O_OX90g(8mi=^qTAPslOS7ef%g?CRnY@RIJqw$zSdT6{`; z{H^QKbd+3tUpKL?)CYiURorG>3U$8?$U-~3+`<Xk9DHIZCTe8ZcFi|F?fQEr;dn8o zH2520roTzLTR?{k257IrVwSm81vkf1aemM1q6ltXt97X}QKF4%=GeW5vD#N(u&kYM zCL3@fpLTZhbcFMzjj)0C>E^Etu4|K=?v*)e9~jw9Z67s#@PEk^fV9U1<oo1g({y}< z6yBQ+a$bw)^#e4j_5hNMnUV2z@kNcLpyDNEGh!T{$IUZl7B(zKC@oMsCjj(E^Ob-6 z;UDGl%y_!WiRdosfFhU7E2~1`xhJx@X6wo6K7gn&b^X43VuHK%tINAjpGf7>FN%dU zFYmu+(lBvx$*Qz8+&uRHDhx@SKKL#UGMbtYYL4k#VhlJ{SSY6U^eb+(f6$Xw5P|Rg zRax+injAOi^?p;6$_tLI<{fqUCILOt{bpVFY$`<!sF-U**+-9@6HbTXmjD2{F5Gx9 zc`Vz@O|h`<`<PYzxs~?yxPSlsd;K3&AIl)aEmP$YS!t;L>txd?wx12%C4{=Wr8c=y zlrG=9rvr|!$#7teFCD&Xw)}q=APC_eKv9eg4{&}U0flF7+^;q%d}c`js8E=j!&CSi zY;3%*B3?D_%V=)^lDRRDpg39ZGZ{JAOyV>*i6*R_#=1KHKY;pi;6PvBuN(kZvNL24 z)WF-v;hc*nnP@!>v}3vP5jYxMIOBPWW{EAaR69F9>RiZ0BR+_|5fru=Q;MYjn3y&+ zU}C~YD&E(4`aKOTAxJZvVTDL2cE_Q~9?Qy}$qnEWM4Rr@#iJGlU7nL4%Ttw!`5^){ zkvx`?l#lyV)QWmu2r8}cp6@N_9rHU3=~tL^s7JQc#mSdfUPrA8xk?Qsf{wc~fQI8F zU8B)Y`nmdb6YUBx`uXl+JaA$aesXWI32j>dK>_G$MhI@me;q#%BKBWNKLK{IhE+;Z zk`<C%N2x@HCCL3N71b(~kk|6FbfeSZ1U|ak99@Uj4)W?jRaBeFB9*|`w)aHiM!njO zPrAFi_n4hZR-D<F^CB(*ee5_uFF$uSB9RNKY^xL%`BB0^s2ihKWU9#~!r1}ipOh-^ z#>Znj`k}aB9&~bwd3QlkDgL|SCj;c->7m+#)j)g_XVk}u^)h+cRu!l`h8D@@qgZLr z(Cti!?(6noQ9r!_J{ko;t%gz1t;|?Sd5Y)!z)N2r&=VmvwUc=HkF(hO^si46DJnn# z^{|&9ZqHkL+wAMe4pM%qwqv3YaeuGUgB=3Y2MOY`YmZeVQ@Ew2rN;sHF1YsTHo7sT zJs+U-KF~LEk;lGU<u;AozAS+x$qqNrdiSZ(OV@UzG+&<LpqMnwKN@Q&wXnub<>NHY zEnH4I6!E|O!nU|aY|n?<oSYnV+0u23EIH>%65cz5!Hqe<RB~_34|f)-23J>`FGn>v z?Cq$B&gHlOMYx#Q$q@w|rjC5Sw~h&Y5d`OfpDOc|qK>3Ap01ZBeB>DA0Mc?=#cVnV z$vS0GA>ZUQ_2-AR0Jde)`ZF99P_Zu3*gwplFmjb{P(3uY#=0N)f{>BK4CnXE;(W`? zZMpSUUJtH0TEG))tQK>a45z!+vM>ou3nDli_LL=E>bVE(n=N)EtUntYza``R>VK)@ z83lxCfV(n8KIjrjCA!(X6~;jvN$~v16d=dli2hYIeeAbxF)KqC6@OXe)mv5B73bot zfqhVvXg8f?mGLB}Bx&utIE*3wN9n`=To4psw?L#s=ksE}k@ICc9tfK4cBUP(FyArs zCnZ|MC8Vd9<}10n3Q!2b4lLLhwn#oKmqb422^<@nh!p-ki6qr2p<m#()E_NXS^x1N zCCFa&V6H2C553Ul_lp-IQBvVwsL;1eSAAzszNjx$9^?J3VDt9~GK?P?n^O0mX`6U9 z*Z(Y#0K(-g9}OlI1oWVu<4}*iE!>d;);jiB30GG?ZxoP=NCB6a2%e9E)N3+8eQA7* z4l~?XC05j}Mww^O3>_$YR_S+=Mb5dCNk^u65GE<^5x)hE{*bgUfHla7qbO0^_=vf> zGT;B1+S`c(@^v8{$Eof9zP=JSD?l~m9!CU9BOQUNf_(BH5~8;^4iKyzwc}lr*S<jl z8shR#5;olw1~fGhR2iMRT32l2j*zdeVD4~wl#>EgvoQdO(xtVyyw7U0P>24EJS#mI zYj64ycIPnt(^ux8?{6p0MDcab_mB>V4m>+6%XGVJG>Hf3b`}GKU_3_qY0kS}DFG>; zS#3G3z4(L#v1J99^ajTrT(B@EW|-+osa5v3WKZtmr4Iz`xj>JMsj8DA#_i%-xU_=M zIj5R>(C{adKjmzB+;rLcd@2J<%w4P$_4_5lQcChe=(!MF)W2AWD~Lc#d%a3|Rsx`^ z^fYa}^ZSeJ{D_qu9X5-3dj3y>n}=V%F?_M&MC_YSPb+DO(S0T8-en47cV3w$ud!GX zI}rSu*WjCuP~8S4I0Bl|hHUjWjoL5|U(cid*efWlDS*N7<L-t}^hib43|6ZGH9doG zOmL37inSVjF)&kI{3+?-o{KORpuHJY-ttn;zNmyc0zDcX9o-nfl5>@1{!6ef7F_Bq z`PtUC_ka)AD@T80z=2zTZE!4~%>I75b>Z#h-D+)KmDBu%_M;e^%7Da+zpd@XV<CC) zX0z%@YN)>ugeZ46UGnKw3SUW+kj_2^A2|X9^LB93H!2!b_w-_+#eLQwea-RD!k^~p zN^S2*<d{I9-2g#4Cv~7JQ^8v9u#=Tl$#C<y75>^fQ$s|9kIY<}B<AqpJr$sU+1+)O z9ykI$6pO4&Tdt{Ec&}S|Dvf-P9QgE)!m|5$$-`6qxbSbqvTIr^>N+0rX`UD7ug!7m zcTt{huUiV5|DD&5e<z>$dXn{`mUPmHclXtEAJ?JqEJc*ROse<bqcQEoHb8ae;Mldc zwal;R%@%dLP{#xs8{}1R-Y@km>LIVR$BZQ#Mk!r*w@>7J-~zJHeCd?00Uu>iR`>LD z_==yvV!lS$;c!%|GA%0m)y0S9hsu+awS|S}RBsp-ySlqEw3xz6D?YXC-^B%4te%DP z2Q0fTd-@5HfLV3lZERfVf^|QC{+(kLmQXS~+iV6a>stP>3UD3hhPPT;$D!$Rwm)|B zwi~Q3nHAo!fQzzO=<BVG+DrgxZ~!;Y8!(9qzy0xWwgvsjgc<Pn_Tu*gxr1h^(o-rh zGVHhh#JqT}1tkiXzuVa0cM<d+<-0klQ3r#^evvL?GQ3pni~d-DxKN*LGoc-yG4LZz z8CMknZ{Qhw)3phbH>rMG+iKFh!%#Yz-Y_4eX`mBb3WMv0DTecxdnZ{aW#;B&<K+Un z2*_8z+@sfuOu*gX^(SGMUpExn2dF%fh6Y(XM?RP$_7lI)dV*k)ORm&^ZxTKBM`m=P zXww`mJ*|?mUB%^+6>)z*(?p{}4NMd0H<}|69Y-QKiiS(G-)RE%P*S=fo;_+gB^7mN z`1or;tzI*6q*zN~HMl1t5H{0tAboQzZU6iWDU2U&^~)+;<!jZ$!-!Tl01hd*u&*A0 zh7k`>YN^ircD_aP<wdBZ_n52pXIC5kGF*%TiaPNR;Ts)@?O_-(z9%|6^T{u~b2}fP z$~OwjJK4_oW8HMElf*H8E&tgMBE<Q3w2liTcOLL&90=R4?MGwV4`wT)u_<Q?Q%EF= z7Qcb8$a%BG{es9LFBGm!1`}j*QEH?}VAStc{|LJ(0fKWtL#JEs$gE%F{0}*oX=2-w zVghJms>rN*m;0fMD#MP@txwB>gu_dXO9du}si&$I)CLGq%xKDQgK+T?cV6@h4jV`e z{IW<kxtv{GKCN%w7vVbn<<+9#D>y9FU8r1Ry=+`$cT}z3i)^q3bn%;CC6VvayL2ko z_wdoEhAiJbl}{O-<^;~iUmCi6&hm>#JZYOX^Hk4<@AhJQA}Q~i{#eI{ke4)eWP1qD zei%whUpC7>C|O+sQM0$$++uUs93g83O_8VGcpT*-P>Z&vYBaUo#u{qs`rUoj)~0Fr zDmr38;DQFo#3AC*iXnOT#Ii9^4i6vZ$oboOe65#n`1E7_*2u{#_CrYsTVwa$cd1BH z^YG=%1G8T}-}buqsanTZITw2LYLGML{gMu-x5U3=AxcWNCv%TL3R;cz1unqy_>2sg zRWj|AMAUG3pe;#p2hB3B^TRA^H+rwa*}TNVpPwO<DeraV-DIDVjx8T%MF>B9=D6IF zjN9O!1lbIGD1=H=dQ6=NIg$e>04=4*Z%5m{_FFJZ`TTOc<<gW~85wAb#GW)KkM`Cs z#4_T|N?VA*cwVvPNxv8f0U0+~2x05CQz|X9f+ddN1gsht_B-d9(biFwUL!R5+s|AV z&A8IrTqra|xJTu5EY&Bqxyi71Xf4AJ=Ul+zdZJc#`j2JAsqtDXFDfc`r>PI;hcMzH zVixfK!`@p*Mcs8_!+;<lT_O!q(jwhRs-z-aN=r(2D?M~~cSy%j(v3<pG($-VLk%_G z5AXN6Z=dH|>-+y*-~ER!*Ba-{Is5Fh&py}Q``VnODP$>Yzv!bHylXg_pHoV#hCD17 zFhw`_7LkUlZ3BpVObo&7dtQh3`|$H`Rfu<aN0r9myNNVRl>CEQn+{;D)`2VA0h<Rf zy1+Ewa|`8#>)|CaDq)(HTNCO7d+2NPFduKv@D!e<^IsUSMFZbcmhVMbJaPRgSzi$g zrxg65aVl+1CE4le?A6wxwV>hS<pK^0Qb8SgC1jCbW|IT=divE2U9uV8pNQ(P;gWmi z(wn}<Kmqnz(hcJqQntHT;=uyh<bA)f3~=a@_elR|QsVN5Rx{<;#qX>YBUGEE{L&c? ze$huh#O!<IV>f{(F+!LoU}IsQtbI>1oQn7M8-O}YY)_NnP(0h`)gW_2v<c`Rp5HDn zrQIwnw3@lwEH_vsaVZPcZ;<~SPUIj_NYau>vDOXqR;F#ahRA-|o9UHmA0Z!ea5&b3 z`&$ZHMK}&8j)LsqC0Z*5noIWA*bbnx*w{CDq#8lvrsih%8=jABNv2UX8Ow)S><J%E z#<^*GMI0^1HZET$39gq9r)F?m*k!cJ2|=ZCZ)oWNoyMU3rssFxZ<9Q=J&DK#%~%|% zY-5Z;E!)mOM-ya?T3k}W%|w3U%~IQw&%ph@E9NmHW4-f{tpq8FjX+C-@5UL+8St`~ zMbATj{-lsv%rh;>M$FSI@WM=P81vA?4!wCH2RvD|j6`QRIuUF5Fmz)$iGSSTN?cfY zzUldp6WB1@CEAzS`wI7|5BfYVX$<HdPY3)lt>HJ<{lqr26TKK(Rp-?~cS52zy9*w+ z^C;3xM%&vC&k=rjLZdID+J}nfC;D)ZpXWil_6tMiAD@oUG2wPWxB`P)S+1#WEA6`J zP3%W~x-_9yw;pAGZ|?=>HzfSW&a8HVi(=Z&$8Y*TS=*OJlP!ww6E`>II~BEo$3o(q zOH<vu;w8E1R24TvZv|{GRD|9NxmyEiE21qdxZbF*E%@v}mXfnO00pde6Zk0ktad z_!rWLO}khaRh_}Jk39q2xw?(iw&B!*79r79n<ek|EstR1j;ZE+ZFpyDh(bx7wiwW( zGL0LiK57q{G7hPMj#`>_gxpT7m$S2{jC;x<j;T!m?s`Ni>z2k!w2DK~?YX1<U{)ob zadoF*s<jsUbS7af2R*&{>tgHscE})sx?w?_$_<65LUCluG2q1`qe^K48;oB9)>-cp zQH3E>I{k8+Nb?nP@!X01JRfRGVJu@B%Z4^kozWc>MJ(pAx8;~FF`mKk;KB5Tmly2b zM#Qe!hYkbpo&dPxDF26yt)4J6N8iiW1DeLM`u6=G2|W|@Eq*iY+dbRKGA}+A&xlaE zq(>b|jEo|w=2oXZ<C$WW20UicD9~ky0FSsUB&}x#i<Nz0b2o=_tEe*+h}0ZUB_FgQ zULO6TZ&!+((Yi13+3mFcyoXy}2|t+Tz&8qG?jEhyOMatt&#{uo^xGf9w)iwk8JjP( zi39F57=H<c7wMDg%@7=kkSJEsZY-lEqP6v`@8Z0Nzc=B4{rkaYhh|lKVccFl<`R?i zQb?t4<FpwbU)mX@s&N_ziJN=VFii8dVZ<I^=>7ajRfolETSdikL6bc}I$xT_g4rfP zI?ZB>3~0o;LJ}t-IHLK1(@TdJe%kb%z;iSnyDX+V_{9?D3Dw79t@ab$L)_z!hiSG= zuLhFTFE^4*0lt8uu*PM0)ofdu0fmP0GoX04l2}<xsAKb|LQh_ln7ONPf1?lySdXko zZDuvHU*7-sb+gJQc~3HAYQMooH+~HL>BngJ$P{cV%@wRMnv{`2??D!aU&!Doq1@qa zO_D&e2DURtEr7I9O1*QIUKEwfSURsxzOe5NTSg%)+-u-W!n4i*!VH!XCFj;cK&B1@ zx7Wq?v}}|3FbO%(RFxpUx?|YqrdNycooZUs50E-Zx^?-=W(Q8SJXvqANN<L#80+oP zxs~Yr@?ZwQ?#v9`JrJ?0Vb|b%f8M2F7s}Eo0o9pVbm+&J{bKRGDv~|Qt=Du5y&QRE z0@22bOS$A=5m%+oXEe!ew0H?>ryjHa>q=z>)`+3umCcM6zkaLE=x)qqKIH0<+d9?f zwtKpJE<T0VSL0t%p;4*DblH%)Qh6%g;(Y+I%a(odHSGoGnAWu2@aAcyCTztdD&cux zP$)p8VlJ4};i$pJ`&J{K!mxCPeCsu=*8`{<EyO|6PMM43LmCK@iakUD2(|-?c{lGh z?M6~~bIE*<aY&9!N3A-QaRUIohu!kj1>5Bw53kmS?ZV}0+7}O3Q0j#P)KqRZ(4xdI z+-z@eD%~I49k0h~cgL&3RUL$6x?%dbeyaS!p{A|RcKGxZ$0*JIo|<(;W1_&TDRuQ+ zx>q3<>k1#dyaHY*Dn4{zX^S{fjLA%4T#GoEV~zECz{IQpY0Bwrxac#zw{Z)wU^iTq z&Nn&jZ~;?4X7YsBFqSIsYBoFQ`9O%%(-86T#Ovp*IY2%9)_^*u&n-NdA3{V(B#XEW zlr6M3-dB3{N}1b(4BM$~fl5=OL1B+KXfr-x|Dn1%Np5Mb)a29*nHUzijGkBeix3rJ zvcBc#mDML%UR`!c(-n?pOQE^BUD+qrU%(Bj3ug<kDlGVXgL{mXEx}?HP|Os`(b5w| z?pUs+`{nuhmzyxV>GG8mMHrh!FmC3}O~29Ep8MLTI8LWxnXu=-oeW}RawMsyLUmr0 zkqlVIBWqEm(duMm;3610ty>yoK66q3V&5%Xt>ZGq-xqon2UX)~cFI;1aZP+6bReo) zl9RJ^^7h{S?Rlhkb=%4LhDrAus=Jo8Z%o%G1K<)VdZAB!NF8LW3~pp<zBjF?yi!sk zJ>IZ$u+$#ihcsdet<nw(`JYjpyUZ9gm=qp)*1C4R-g>2}`6Hc1!k*-IO0%{H>R9#G zHJ3I~Ps4z^rxqPCnJ16u%6It`=KE_m00W4$`>PUWBh$uP4l`(wfRMs{Qx1jIQmfxC z`lCm33zhL`AIq6e^f?=~9T6LjL8*)5Q&Lui6ZEc{^BJBJ^$c?FI~ajCSy+d>a@#hq zP}gr(=r&=J*On3bni+&~gdjL|ta?_T7I*G|+h~obO5{<G0WQJ7&`|Y4|1yq4D*{NA zy5T6?aT9`cT#M0{5Nr#4OfOq$YSKD_)Eq`+zWM2^lF<}PANgpv<>lVQA%5PGV-k_9 zrCMKcOm|%<W3vB14qCUIA|ZvqvlHgz)6Qn#a`0CruyB_rWPMF!j)e@Y=@=CZa{gJ7 zsd%t|khQJDE$LE~R3+wVDGQKu6_=FQ5@c1<K#x^GZ77zOmhodPZSQW!*E$JonDZ65 zgLLC5x;dR*d0(F3SO`}4&E7^}BeHTu$W9`uAfWpJ`_!Z?zDa~}u^@F}Lf}ts1n2tq z%Cw_bd8ASaM*{DsuzJ>sn&zs%J%SmU^IF7AVogpT5Qus1U+E?~Bf4OC;l`2TiZ_Ed zg53}DzORM6G!N?y_dU%cZo{QA7DaY_JT-}0i98?bHae6naqh^yo<`F{X0C76kRpl- zY#uUdDk@OAn2WJ5P(uLt`No}nr9)}gZ334CIXLH@CqR<~B@nWMc7Z<FMZ`lN4b4iC z0x1ZGhR%$vjA%R4MYuISGo9kGn3&S}@R^|aTv~pY#XwAzBs08G<w2%j`4txDGed4# zMxmFAnO-%5TYGV`9qny_q|ih2+n=yT8K0t@_dN1F8%Y^kAv+zJ-cvCS0r~@gzrxKx zJDbo6zuOIbd_ccYSqCTZ8*LZa9UNg1q33I2VxMjlQK6$BjK`6hwUw!#cnTK3*oU~P zzAhg(b=mnbdNP}}b-AoAwwPRC=#s@G1oSlSa7<)<#adPDq{Q%qnW#?TW#6|X1uh}^ zYxodWf<Q!tHau^;efbIaqm+?uV`T<axEklxqjIOA4@n{Sf^a`N&Ak+2c()SWE%W~U z>o1()u*Y|vq6K?rqdkbNKj~XoSOb`eQ9%JKtEjA9P|!UhJ))8uUR%BrwwxF$esxat zp=8i#asc@;zssTGmAulzOh!{ni_U`Qa-LCl(2D33A4MT;mACmzdwTzVi47%?9zj69 zoL`zRU**>)^))rGM9(f@m72S-j;pg;qlKKSTaZQDB4m6}uIkgr7mizA<Uf+CJzY~~ ztHz&KS|y(@Qqp<SS?dXmS6k`SShQT6)b1p<sZoj$p#64nKcyq#Akk@>9^6Y*h)YO1 zbiu*=*dgHQM*pp;{M|Ztjj`m1k}GvIC@ZQjy!L7%m5`9I$ENW>*Yi47p-N-=D*K2$ z6~U`}TQ&5k|KR1T@fSq))%KZtL*hOdZyzb(BqrWBf2knRwW&&jrYy4lW+vv|<v9UQ zyU%$4o37ob@K2BuUay|l$|M{1LS{tIhTJir*0;)>A}m`4(HiB1EA~@g=<mE30u&Er zX=;KKORhIA+FO`8I>y>9_J(%lJXx#c&uD{j1~gq<8n}hl+MRdDB@paK3$;;j;t0`$ z-0-oZ9W6V&pVJjZJ9Nvw=Stz%kBooRjzlERuvev}As#Be5+{CWyRm5)T7LVP^TzqJ z+wl%573O4l&Uj1!3F%{IJ*VSML-EhcU+inwiqA<Twu;ay)9k@hkDxVihix6MnEl@J zm*>i<rsn3Cni%r*ck1v7gd~R4RmeKZCBu*Ml*_LfRH`@kBsw*9&Exdvlv;#XPe%bU z9y!mOkrY_1R*O?}X|(=E<f9Kuqq7%di$=<*1<zHR3XpI-5_u!7-PWo_ddZ5iR$R4N zvl<Eu^Dn5f*t07u$6_2%v<C`LVG%+y>HF^|XVD~7XY8*-w>+In*(zJK72#XbQZDPR ztQ>}y6>f+?m7WdFrM<T?@qxb`!(5aTB#iH2FeYmuuFeLjY4o$ckrMCmOs`aWS^cx3 z@M}(aT<H)2rVvH`X|AN<1HLmYi|Y?A0kLaTW^+(9RY}f@!O;$nU!Dh^T`_Tj@J}u7 zl5qHb5877NlIU>Jxx-X|>Pr;~_o&^_4qoTWO+!;@5K+4WibRpI=myl7YXA9akMo=R zzn_#VXxqs6Zm{h1>h{VdXQG&_<-sW%u_w=ER$gwH_*@+>4<E8E1FbiI6#W8dJ-9*k zt6f=2utDsI&P0wH&l>LUs4ts4H%B3qBJ#%coyCEXL{>AE=Vc2n?m|X`Yh*qN->+99 z^@I2jkLu1H9!VV<h{<G$i^(1?iA5}tGKU>3rl-v<A9SU+S2u_xbwEtY|AQwi=cYy` zb!63?2U4Ou2lz(r00IBv*6Zh9;D|3CDlcB}_TAf*nN>$WbT|aNhAlI995Eq=zhD`4 zz278yKbkB)dhoP?g)mybZo|#@%{w#`E;1p^v{HutqmHA^;I)dzqK0O8?3Va#6MgSa z5fv8`wUF{l49%O3!?g@oi3awo__!#7aZ%^0jWgBdFQ&u%+$OUz28MFRfsr%l4Z@vS zLBXrt_ru4<-7C~XZ@s<tPtSYnXBH0(=_o<JciG|2{ntwnBK_#&gPtdVlqZ=^RL{8s z;Ep`yph0A>7o~Q$rd82CH|X`D*5A9_bDP{e)4ZNdKCoVF8PtM5-xqqas6)%cqhGFd zmT`(p*RnA=!9}t>mTE)cEhvC=GLLvyZ8c*H*=?LJmIlHz*2=v<v@)-ERJvtg4sKDu z=Rl5vjf?^Ectf}`U7`Ca{d=4K74EB{qHo?P0*kHZEW`0E0-^amJ>C@TOX}+C;gG@w z<Laq7>)JG5_xrZD8O|=6I_l~LPgq!78Yv(oSOaA98#pmx6db)dx({gv1>DS)+w~N) zj@k;8ify8un@^I+9&^n!8+aYNwt0@f&h1LJ`}FDeL~ied;Y$TEc%Q*d7oYx45f?LB z`rZpmv_i$XnKq4J+jFuM?LyL4v(pC?UeBg5o(^V_Yx=%Q5YTb(x^(4{I4(-gre*_! zhiwmIl0D9->49cz-N!%Bu~TWscsCW@uB$~T!R-Njjy;a!9h|p5!`_hzFQ5N*<~<&K zL+FlsV7k5S?Xy1gw3FKQq<nH65TIUI^Z<H|4P;3^1HE5t;VXoj2(!^@Zmn!CYpXFU z=vEtn$^`s4iMHGwYzhiIJ)aKTk9YxwOIYk-R$j)=P*(~dKppq&+IXgpDzB3Cyc%X( zKD=LNxd{Ee;KI8Ff9SpR&~}(Us?gmSS!b9+v6@L1K*A;ymO3rb-`IjeQ!>p*Qxoof znE8w6Ip++hLoXvRzoRo#%rn)NUBsD+=|SUez3Ar5M2A&amFu$f3A!__RCD?&CbRym z)8cWV?^G!Y`YYUu$57{)>1pAIPIcVus<@ahUWB-oD?a#rYQ8D>(II(E1wZ`G`-mrc zuqYOY;5`O#gNNLot?=12uUS3LKY&}+w#F8F0Aw)U;B1AiTWQ!(^UFMMmLdYp(z3KS zl1lcLR0i`oQE|m0{e9fbZ)?|!EiMm%CTH>6rtDTl!h@mLW8&wmul4owF5f=q^4%D! zU#k~bBIRm7X^4j9MvtHgJ5zBME?f%O_ik*Z9j-_p1O;UE8mnB(FF2nYi&Ku${oX2J ztS=Az#_IE4TC-CWH#`pDCY3xCzxiZsVv+HXE7g1<`x(sFiqu!)umnQiKq|MXW$nA) zwSTdYZvDMlt$o|NRoKOXYlw|izjh)i@!+8q)^xa1T0;<o(NXO8_!zX=F~Frut{!xd z!@yh=5)q-e*p1zMK^UQqj4N#6mDa>IG~AmmR67q9i6MxPLuX#Yt$zk(Nc#+F_@p!2 z6Mna~zu_tT!n>0-5vFdhO+vCE)xNe)B%`cc8Kx#<k^;P`I5p=we~2;`<zu8Uk7g(? zT#EqhP&I69Ku=h6nLjt<HvgYtfU&+3z9Z~>HyHfOeM8VpNFGT)HKVLYsCG2#B#K;Y zx;gF<<9?$d&BQT(xuI36N}(%?x_Uxo2afG+o1?MaUoPa`BcKz22Js(leGv_(oMERx z(drvX`I&LktvC??phzaEhc;$<UadfzwW6K(0Ip*OjAV}DU?c%|1#-dn=8*S3|GhLn zNqoR1#X#{8%&e)VlXUTBf-|YIWKr8KecN2w-hRSu@#_mee94T`Vc>mX@CaaN0Yy1S z0d<_$XkudmcKSDZ3;eZ+mV8h0ocuxc1vyx}_EWYUNuwA1&G$-gbONG@V-+5O#*FRx z0<cy`PG?a-Mc>W%<(XC1P&hQuM8G%mME=+gX(sYNv-(ttREG4)cJZ?!^mvnxlateA zZHi8{jN&YTEin{CG2>2>tFDbjI>Kjb;_9ZZ!Eo5>yvy|c8~z}Qp2&ap%uliy3lP#z zzDH6=^0Km_*VmDB#P%Ph>s#!(*cVt6IkmT6f7CE#hnxD(wr4o+EYc+=9yocC+;`nF z`DYL$lu|%Es*DQF4JbA8etTq+HKdOu-p5AcFq;k9?)fMyXFdWt4$i$dI#7`asj1N~ zgbWbp0<BW^76wgxt~vkGpWm)Z7NCo(nniT3vM*l_KIY+JgRbGe?UcrQ#8OjJqomSk z-0xED_Pw>x#-U3RtbT8g94GZbXr};QA2dNEtU-Py!Ex{(J&FOs0Fn$-E*N@jV)sVa zSorxhBE(KGU?6I!##@aLAqk(|ubDBm3Z}B3XSH<*g-Ayde*4eA=Ofb!Ooaf!md)k2 zce%8bOt4&v)!H6Y7S7%w&HTM;nYK!~Qw`y*=kTMuw6xTltX2B%LjG%`X#)Uxgk%rl zo+>CQD3F$ve8}-3i|my!nxuQo$2e8jDjV+euva8Zu~GJonZABTbR1Lc-#P*eB8fqc zbisk4?Vr9NN<c$OQ*%VrMDE|!Ws_TJ8<pC{Lh|=70Z);KAvmkEm||UMIx6#tX)^{r zWX2mWV;EK6zI|e8WktW6+pP1Sc>y!@!e6l+MCZl*u9jUq)pEuncYbklf-M%v$eM+E zXV`Fq_%BTQ|GFmrlH@m}&O^!B2k}Wsm~hL?XFN4BZyX$8>`PXxwBRFB5|Yr%OJOB? z2KGOGL`uO=2uZ4}Jw(G_(!n8YU|`^_>N8mnR@L|HgPJ-m6SHk!C!}Zb{#gYwYAbOz zx?j?}J!&76-_}Eic}|VC`;inr3CW@dQI<FHld2~~VAp*@9Gr#is}}?B|Ji1Y3w9vf zGwwwB=l~_5PwfNznF3~LXeHwXV1Y*X<*g0$z1yB}L2R(wqH$Okpz?cMD5QU%BHC=g zvqjR;z<R#Jsj9Ee2p#6^C1)c9*c&LS7zl`n=6x-X{k?%3zqq^{e`@M%#>Tvh|Bt2O zV`L&ZBB73F^3cCy!KWgkHv-88&I+zG`jS^|CtDCOMrhU@Azr`kQ-S4Ro*vt_<t$wo z1{NntfX1DjosCrXsjK^wwd}?-b=K?qj~A@}V=3-_!v7aB#(sb7sy4G82}&-|yS^%h z%Xm(N@bA-mX9`w6`N8RBm|qoQ|2eDQ!+etivMg*$10?^{tvfAMWd;N$toustAC>+6 zFG&gj`l%}cs!{&;gA71OKdo8F{@k*=QEdQ4|5nI~f%?B6I0Kh`aczOg|4yooARAdS zt&|r3e?OQ6kpAqk#Ms|R_#YGgcM<<3Dan6#;!jokSDpTp#=i&q55w{QZJl1b!vo1D zNmTxD7yi$Uk{t-ZB~Ha?Mt_>(J1I+614b~+pN0CrL=OBfsyic?^DqSYe?RC2jNp^| zg>L_Kf&tU&1i*)q!8)|}|Mvr8z#Gecl)U!;GJ?+mOHO6!|LDKh2UzmEtIz0NnEd}5 zY;?eq|GS94#r5w_{Hbc+{#B>HHRIod{ikN!*}VT7tP_H?^WlHE0RG;}e-HVeTlw!H z|5F<O-roQ1&ivnS$p3$TuzOfJvjAVP6WM=z+k$|Egd;aESLSWqQS9M{3LWgT#nZ9Z zhK5|^<m7r)mq8x%((P5G&T`^^0*<JFr|Gwhj2ggzPenx!#7kwoyjlTPA>wLoZsaH# ze*DSF$&jBvE!WNKiz_N{+_2Muro?~C9TkNhK+xW$3n_ehFi-@$gXFlm=bUS+C<6Ch zM!(|~A4t+Jh1ANweXAY<G@z?4vW=SKg#MMS_!|@UlMJ~7VIPyoCSPLp^!0?r#{(h1 zbm-6AD&L+1`iM{v$%m31AS<Y?tgKYlT{h*rV|J-K|KXqhucR^H%JNoHN=@iWit_<Y zl=)hIF>g~92W%4(5`FUGD+KVT*BS;)tPx4vILQCCcwXX=p<$Yy8D|`}py(5#7f)?Z zCU~C7SX-z2eEsk+#u{~2UxRgMc!)PV;^RMy#t+d$_CS)cU3A>AMTK76)YV~YHu?yF zYnl`M>J$X_pbCYlKgp}D&Xt+StT%e(|CARCATQc_p`<eu?mh?46zw^Jxe7zmjUMKn z@P$t<m1>g|i}zl+CWe%jzDg*{xBla+_!f-7ciHg8<uWDfT6e}rrX3P*KbC_m@;oII zzYjcClLk;MZt{D{iccx6QmuXmGJYTFZ%V-1VA1lE8wyi&LV_{-xOw}verG_)FCtko z5ZBzC5a;L17LV$@rWbp2Y80!idg6cJN0xWM?fR>d)CUYqOnhSA)4V+)IBdd9I?#=M zDkjy}uQ^{SxXP8I{Q;Qy`8@zO<ZbbrLJbrLsg}Jxy}nZ`b+)swK==RyZuxW*>j}RH z8lYFRG@TlMF7P9eCg-R7*abt~zv%*KTvdA>>QHPTo!?JoTDJs+LYp5A4Y`B^Bv-P+ zm@~hFb${uQ-#GA$x=`%*Z+S4l+z${Cv;@iPi9g6MEX0JDR+c^l3ZldlyZ!_OWhy1# z8r)_F4YYYxil(DNl{#AC%(6j}0Mt6$?ww|pENP<0t@%4D^?!cC7l=Rq8js53!;e-N z8U#uxV;J#?i0F@DBIGzor$&&53SLwhjZ??^e_%&(K(klwkq2+nMW@6t#>U2-Vgx-2 zU;+TkeM^k!VT^~iMRc?lBws`SQRX^Q;N5q{`nYo%WoL)%cZM#17QLP%C;byo)PWr2 z&z~XKIC28A7geZ9{|MmQD<E%8gVt+O6G&Q7&o?*Orl5`aKt~&V-)Z~X>&fZqklfsT zogNwdf98g<P20)fCp?M5J^P@ir!UOKec$Fhv<I{gDq6g`#38Q1@-mJUXjSmhULhx4 zPA1)v7#?yV8%95fbh=+j^M?g^eh;YwRR^oiE{iKS&$up<``cGW28NJ8+{|~L^Rcl; z)gQmAG+fEd%gqTs_C$;R^ANoSwB&L9CSS+F$cS}Je9y>jMOle-KW8pbPhL^0Bq6}d z8)9eXW!u8>hUdKU(U;zBI)V}uJ%PWqQ<4E|Z&!qJ@PQtf9|Z`}^<C@(iREdNFM=a8 z#M<FW!FLf0%wQ_hH*cV3`}*A3aRV>LBlJ)!DgRyotq~dk#Lt$_9CpDX>~G!O_fN1C z1496E*N8NPzqsr(+l3f$D$+4@ATHHJo@$f}XMUQ#n_~43mT$q**|?lY?e!o)(nu<H z*NlBSc`wR@37=6eLUh(zT5TzFe!lR$Vp)cwb`6hAIM<m!3&$U*y9-HA*JJ-v92m$4 zO^<U^Pum90_C?6!u4Q*9vhT-$C|p0868HAX8h!7|(ubJd8=93KJs%w#BX~K;l3SCz zP*eV55uYY&#nNvc(A?QtbCvvO9~b}GX#!eFJU@(L6Dlrlaq%VRiQdr;?|r9(ANm8# z7iJ&&BlndA5Dws0_Y64bG~YK*K8lYmsC5|)icdVJD)o;Mk)+iFB!w}PI(5+kp!*TF zGw$T_#VQtUp67fxh11)|9YEBDAM$gTq6bgHYl5kRJI@gD6-aRZ@Hjd;dfPHNmgvc! zAq)%wVE4N!<oMb%pBQ)X33dB=>9zK~{z)|d<$WG|Al!C(CJ|CvR@&2tgH{NE!9-Fw z<L2H-3IqGlFajm|TL+L(=r{qh7^3;E_)}J5BIhv(bLK@RmWhd3%0cVLuX+>Ln<;FX zoOZX>y;m`Lcpr{Z@HPQ%a<W`+5g+qW=K<NjaS;qzU`A5a(^Bl4F8jxy_4*>A&3;qm z2mpo8%{K{_N4xoTgFSKcCf2>i=7Di68C7lL%&WJ=h_|V~qW_5m;v1oOmElxBz$*B- z@zio|L!!@!5UkpgDA{j0_3rq_bwUic07#%3SVc1Xke_CXHX0cUZN0w61@29jSj;Au zzwM#_)4LQhY}VKP3egH>8(XeFxOw-D0kV~*4-r#S>QZM&znB0HlnJMEVh@w#mf1V@ z{P1*Zrm8v~BZ|Mp<9C-(y{#`nN0zZG$HFYYU_3)-QAR>&hPbGhSsheIF84q_ne+9V z*^s?NKEgcWwU)i)LjK3Ne)<AHT6B8u!a+;z-s1WNH^s@E`rtI`HuG_6z_qYz8P(qe zV!w*6JCh~hAH-A6P(aeUTCCreLM#4J!OJ`3-Z0~nwTwfnualGFKwp*g3P4K4hhq#B z&82O6#<B$C@bdB|AEd^l*Z^TxPvqve@AUN2uc+qk{e4uCkd^LWwEV|XLfCMIw@cS? z*F+(qq4n(9rKLX{(wHeW$Fq!EAgbZ;`--kiwIE4bTalRb^dC%Fe+E9Bhye@RuY;MB zY-D5%;{Hx0{lv&yn#!XSV`4?4LeDn!P-(OBM@Au7zE&!*BwQc`xK5<TJpan3`O8C= zbOjW}sfrG?uArz$ynj4zMfu+1b7E%Zd-7jFfVKj0-iNjjBaatRnQe-&!4trI6AUZ| zY#HqRbD`i<0%HWMQy-frEN0f$I7r<JJ2m?O%_ApNfncE`%zIF;#VKaz{UUe*>D_~M z)51L*dgiYTe|S#WWx&p~Oh@$D7Zes?&h4i_(>t@DcPnCDnI4Hwcy00IrE@()QHYOw zx4GpS(#f{<N8m&XfOq^<iy1*iisJ+LA4)b=%J?4eK&4(j4N^-ksHs^rn-kxv&~EEG znO$l-7Z_!p@boV(w%F|bl?kH%$7Z3>0w)hCx_g7zA-6UjI{C4g(x#H0k#CeYQ6KzD z33fB6*JumcS<L`D-HjoDtkL&t6qNVR0Fw^@#h4bbel-r*GlyKBSQrXGKlF^_WX5o` ze=qGou`m&ZJ*vdC9-sI>8jW8KD71|Al&8-sSxU-dy05L_En5X&iV`GCd!xgK!XA`K zUk`C<frm~m?i6)1ZYK)~gmeqH=l#zJetwR?5Q64piHrpWML>a6{FhdKDo$2mraoS5 zW^;s{cR>9^9HguLnWEE5FP9fUhH0KO<7@1{zmJ5{4xq3rVEtJdpbIJM8?}-CqTrie z^lg-L$hg;W+p>=?VK&BDhMcm2{2O}OEz|+K@t;VRPSW7XPoLbr1I&uwtBpPLiqyR< z3?s6>_xJaQDrX$)1B7yK)C_DJ21W-XCx^FMsPG3y6iI<;=nrJYq#A(=+&xdWS&i7K z>tsr?W<Y+#A)k?vdHexpr5Hf<8bU?U(S%(OEOm5_A|Fq96+Lsc<{}ny-=8N=vgW;f z8=q7^$lUGgU%YMcz1_Qgw!x+h@%gpX3rrJp^RV42uwJ_BSjl6~F)#(h9Yz|CX#G{_ zc6g&A^)t01V1KEi_5xC$6gr_SrYu9@OSF{V(jt5`=1CJCOnup?)$u+~AlS0;FvnOv zT*A;f=8@~RMU~Ojb+}#6I*_h1a+4xt)Ea=*oiQ#9!&^%&<024iaXq^HIbE*LMeThe zbTloZ)+Vk|bPr&Z0n%!-xGI~jQP%y{Yx;8%;^V`ZGrgW)Uo~sW+U!$DMH$PZcFEGR za`~!CH|b%|tVT!zN%#YUgU*FdUsaPNf1G_?2r*a8GD|&tTbTaMe&qT3JaJ>Ug_~CE z_7*?fM3DK5xk|;XEpKOZm+m`gNX{B)Ci5Bjn~Z(g(=`RVa0<J2w)|hv(OaUZ#hp`} z4sdup4vKI4B@Nw#pu;YQFNvnUeGYi|*z&4EjT#?ud0u8fwZ1<F<cO+ZZ`+B<SYL$X z^#p;^+Bh^IH;uMB7FXc;%I=ly9!@(KL$B4>+&&AB`o|@_`_9*LB@6&kLpCZd$PNk^ zsP=15J}ZpIDN`<}N2BP8i5nvZy9j|#YSfNi<Dw|vX<VH}ND?WKAzffCuel-l*4RU? z@R4}y{zMkgSTi(%Er|t>P78!L#Kn%PtomA;^OfrXw*L#v@4Eg)nN5&WCkSM{b<uaV zt6*(=eT?9kNvod$yyznUlhzb~O7;M4(RAzwn&M=<y}fCbw~mCKJ^RtSmDNV)L9QR8 zUN~2~6&k19rZspN2)>U5=XFNh8mk)^bPg%MdPTfDeQn~|E-8SN?lXV1HrRh}X4|z_ zUBGIt_^e1_oCN3=+h(&USbemnP(_5exxiu$%f&{mBl%T{$Y@A<{!SV5BkV9f|H{GR zY|o};B9)I#36?QdUR4B(nkdXnWM-a@@3wxiN>7{hk<?b3GCIw-gx_f!soHcMrP`wx zPpatX*r7cfpd%b1Nuvy;ES@aW#G}hv0NO~FM00OPx8JVWR6D?3hwN@Q>LaPe7EEtX z;?7a8f7I4=nK!K<3fn0^N|X_0I-apq`l_M0!?=uNI;4-6YigOZtVwhvVd%KC%Oona zwznIf#SnXem9Wnfht8605pkbC-QA9_mHaVdH-=Ew7u*ud%hUTBIeez4(9A^VFHg&K z(;JVZT^ii=KoIy&gru2SLv$Q*jFfJ+X4OF@SGak)kCZAW0|$pXkn^mfciuQ0;BdRi z+y?I}>uDGb|FoA&Q9fB=Wv+=Wu=vsRixhr$FpkTOGB)`n*9v#K$53^pW8*N^UdQ_Q z?e49gVObc_{k$<9!(i)gkUF1Cw~Mb39lHnHTk_PYYhm=sI1$UE*Dn+iKNtNBT-OJE zuACFyR^h=E630aTU+xMb%1bBC!#|8aGi_fNax<X?S3NA(Hzs$FqTUoE0`AlaE`OjH zYhJYCWLN6($%=}&kNWk~-3}eS8=M(^y6LJ6in?WH_jSaK73Wl!)P4JXLj=?k1H(xY z$a<^0*o&LF7T(VkyA?p;(iWB0J1cU$3F}S^M10JJd+{&D6YP0ATgZTqF4^>PJeHIn zmJTWR(NR1y)$><$kR_hO0{S#(`eZb;wDeW2M~R$aXj1x+bbZCJc+$DfjKjwGjc$Wn zfbM&$QwsJ;J^HQ}8JTur5$BVqzN~gFwOJ`RIGe_%8w;rUotRJxkezOW^@9aWp*VUJ zw6d)b6XQ3Wc0c++x;;P|E0Z|<gl+X8ykzgpqx)1dB#%ky*9CECC}w5a5`DyA`9rST zsrB{ixz}To;#=~EnoqPEyb78S{zU+{(U_A6maCp#c`~nk>u}!TZJQ{rCN5gE06|_K zB^#8%uyo?;P@K7s`q|L>gx7Tk7YOs(;K)tR*PX{<kcK&&+Zgv`n-Y=k(6;M(vMQf> zYT@haDh$sz?m?&V`Dw@fT*QDs7mWvCI*_hL++Mj;b=8iyF&TJlP*q#1`$LR9&kyK0 z1rgXYhcS?hwEbU=RtN^@;qvSeGvBZ}Y&y>UQEFB*P%3={WW}~<D3p|x*t8Fxcn9O| z_cD^IJWL{UeBd^ZrE)7mxZO;n7|2Y79E_Tb`i*Wtm4k_qPd&fr^Y}%ZYDq9aHcP?A z0j<Y$-4rlHbs{XYUuRAob1C;A3E(HCUL~vHHrt)%AgII_PU7mo_DF>~IQM6{`F|g% z9i5O?Jda!4ZFBDu-`O5C`r5@<XeyN8er+!wh7diE?(ZGFw2c(JS}2oISFi8yPu_oG zhYx*#g-*lUWnKFr^Ji$=?bT{{rTs-Avt44dJ50lV<Y+5wH0|cfJKFem*=L>1m@}rw ztRSt!dqL}9ZwyS$x4iwl68sV=jg+8N;APEjM|$noxcoJ80lVbGqfrZK>A+~B(>8=Z z0>t6)8CR&^uLx!~@KRpHNxYMYDeEkTjjEiFTvO~Np6Eq{+e(hP=-iYGjr)y5uB=LI zSj#!IbuZ9w;?ASsAeY)0)J}!e598&8bThxzH(NQJtBu;8ZnGf;H%r{m0_eqOJU0xz zm(I=!PdJwdP-5g<LNb@GxpYp-1doe(sQP0S{MumC9b&BKTI+IZQyxb|QIyOEo*S4^ zYtbsrb{WUn@>d?<i3~*Rb3KniA!;g@B{a?O4_V{CEDY^jQXO`eBb*1u8^vUn>IPGe zT@Rejmep14^zgFWf-W{lmo<`(3X!u9{iH#@{Ze+HiG*Ms%pjJU*o=0}`1KpHontPF zu^=kJm&E%|8gBGqrpACfl8k_nO1ZSTCIPu(vPG5Mi~E}sE-JU)-Zvn;9zz6wZ_)8S zZtB_2uF))V;GPSCgPU?cXSenFdwP@{+D=NO994xdBj~0ffi(sR*ryFHilh%d#mFhc zh*BjYBm{989%OBP?w<<URChbxcx#~Dm`R@iREO7eq`>ob??Z3!7F@wej>Hk<8`nuw z+{QtkPOuKMQDM#UQrp{tehJ&QW#>pftC``bhMj~YYNB9D(H|}}b^@E5Cg3)>?`m(O z%vGc`CD1*-dMM4qUApC+zqcKpN|vps=S{^q;-}+yW^SW6XL43vULJrMxC$!^*#$ET zAZoa)tfB~B0XCn{hKu!~ehbZ$NRd_1#-v$6E<XrW+rs-Dt^<lKAV;?lSX_|DB)54u za$p}sjw2Ww)iK~TWMwwQj}%Y~H-8dk@Q{6f{t8A9dEC$Bg3+|esMj{$24#bV^Nok! zJT%48B_%66S3YQtAbsj)NyP-@a1y7|;j$Q^uA#vv@@5n=T-B<5m%HBh+4uUpg6;W{ z8M+X)?@x5D7BMIuvmt{V&7O9nPUC0yFWuWfHNkQE!4LF9vBU3b%B~x{wuUus9_zXj zS*{E4;-($M0srEr$!5MWQ+NsDW}#uguCT)#yci0~5D8xL6@h+?ea9fAouA&=&1nN^ zSUj~0E6o(G7{8fV_*@Aagv~QHKkH1ISgL{amf74xKO=E(K4a4y2&$adK`;;0VJY%| z8j!mWW?+7lfWVE#$1uHnR5zb_MTm)rB&A`~?57KsD{R>o_FB(sy-QUwGr{~OSY+tE z>^(DT+mXKH1Y2C|lDOr|{tEQhfSj5xF8-vm(zxB$(gR4>U3E2prjfls&-y(Vi6YnN zt@tgMBz|H+qBP1#x-4ql0?$L=H=;+ASQ=?m;~h|ynQ(;nae`^{&DANlPgE^Oqe%T~ zyXWn}+t<h}TVF5_D1M~lLd$s&D>|G%Di^9cG8ymVh%MNXnnIxN9ha7gHgM^n6Vki# z^L_D5+w|KFkp{4^*k0FxNlnbxMfh}ix{W3(1pk{s=Vgc9e6X@#J4O%1I+&1fPdDA0 zCCONnblc=RlIm-N19v*ygJxs-n81S9@kA)@BcrRRdGx0F01-ntm+)`{yHNEa7MIXD z@5q@669r5Jr#?fAi;qwC8vg2BrC%w`HfCe+*yT9f(cN7(d>sY;JQK2*<VqGrq`$WO zjA^y@l|w?X<Y@b{Xizw3yT$<ge)$h}V}0kToi3~~RqqG=LmeyE6I5)&69Fb%RsGcP zqWy!rG;_h-^iIyU8R6`~Ed!QY*jidet*)03P-$;X@l|Kf`Y6Y<aqOY)nHi1Oc4z}c z-9~hyPJul<(UH+j*!+_zowX!w2%zAo1QL&m#s<f*`aTGm^B}AAUGYKm;SeQ?nUqX= ziH<k`75Ir}1i}<1B8r>L3gKxY(W)M~WtqM6pACIZD<BSU4{7_+AqBd(_8`MW4Hyj4 z>}^ys0o6J%V@-<Nf<yEd4|Y1hmtV@*d>fq)%*3ASx->Wrx6X6$kwp~!Y;RihJ(N(y zgE@D}Omyj(R$lI3X$Wyh3^5-HEO}`TkI;Izz!3)oS-wZ0{W;C5>#r_gFo?$c-J*ir z7~mLg=(x&0nd8*tfbR?J7Ni*Zp1x$<Do{m5p}T|X<N1Wp^~3o}Fyfw;ma-~2+>5I> z4u)%WL}s+0G9ir_u|_8pw3k)xgbrF0M)QCni_jZUyO`?8t1_i4^eYg!x(w!%y6G4a zPO9a~k@T7R<BH4-_MCWD=jy!;2h%`2!LEi$xZ{5R2!zVIk-=D7yLn&D4eXFH%LIO! z6d$ki(D@7+$I<9s`+mK!!f2<8O%cx>c3Pwaa~|6JG3UXV|FZAXN7f(tq3g0bI;E!H zYnGsKt{Fd?w-B;>v#*WF-n??C5j^_zG7++9vpvhb?2sgp?hv!lAZh(Ycd&N{Q}&*{ zSo%GGIpCO*Gj?5@>sSh}-|`i&L-S20o&aq|mYED)*5ilw-@bhtvIriQ*%^Cd>|S8B zF42?O_A26L<I$?ax?8iCs=l{(n&YggiHYEO{=k8#b?w9LZ(lF5N>5)~+rN_JJTyy+ z6gtoYk0LKK*<C{gKbA3Mt$EgrXzs472*H!5wK>EkU{#tuOzUQ<jdjjeIc|HQh}ocx z-O*oDzPEX%&0h~%IPQsbX`PL;F1p>2Xr#4{No+PbDn`XDE;t`PzUk$K9qc<?1Wlnf z7n1JEZkBOL*n%7NSl{$d+N}sezGPmV-)n$W@VBI$@Z%Ge>hv<fHe8uq9m{8_#`#g5 zNB~r5Ce{8aCmhe(QYST#@lAXc3YBoGgt}p^N5WB$nR$5H)!G{23{LAc-a94G(dQnw zTvML9TBR4KeYZ8pIYWZ&3(1D>%*&2Vr30+BqOYQzNJ0pCdr*sPZygeD;)<5M@i3L& z*^aTA2PCOvSN!OwX|t{$e1=FVI;dY@>Y!Y9xe82#1h%bKf@x~oQaqtKEaIP&)2+p1 z%*QCti5M@P-f-d017&?1OEq)@B@Bow6X!taU^;<v@2Y~3kdSs^aE9BD&xP<?v)k34 zJnL}5g~IQBXPrnkqE4;e;{-z0IgLBTFV{Kn;MS=(4=57Rg<GFjLf<EtMBx&m<U9eC z{mFD{68FUEvcl8PVAt*0xw?}dKi&*;y)Hx-jAx;EXu{<WaK;I~eGK$02KoXSIY~#^ zw`dJH(*KI;Ff?usrlir+X&H9#{33u&^T9ih8+f8sb&0HAgf?8A1B43uE>!$yJLZVD zry~=AJcG%&{K`EaFH@3I9@1-4ed7~5?O9CB88!SBzQOOyFM3sV#ev7gxy15zOyr%r z5f?u@!Y1L#LVNcyhAR<8DwW%}<a?tv`tG%S7BAxbTTjQ{4nOKAWAl&3{|}Da8Y0BQ z0|{@NQ~%saou_NNGp1izbk(ASH0#!eW~C|6Zga%L!ZNjuQskoqd&s;YP2qpGU(x@f zVJ-!`1FbKjI#WjJVdYhvuux>vh#AvuH{N;cc^7P4M`AIF$Yh`Q)@DL%kea}SXj<%c zma4@tK;>xA6p9klp1}t><`r0WOW0_5XDhfrxvr>!_|}c!A3YZU(0SN~FU7F)OmDk= z$2$b2pj&_q#y#{sJ8;{n9QX*~xXBJc>Z;<9QQxQ8hKJcbJueA<Y0^$FqX-%p`nMVX zDhIRtq;TJs*HBZla_Z)QSv)TO`EzCYo!z44l71b)-y?VEcd9h(!N|-Q%8*uBm1F35 zY4F@kE^$`dQj8$3Jto+|#IE%$-t?Qq{rBFU!|$y5BOW=|X#u75JJhbr?zN9jPpb<d zspj)aeoxNRKK6VVb)C7qiILA>Y_KsfAu|SEH{6t#Q9y;?0{%cVMyB@xpZyNwR^9v9 zIL0N%EQ8tt8sCK&n>Fi^rbFc2j+;JjFF1VFb6l6Y!G8T=R6Cp2L;MvStLbtg4IJ{r zj;q#RX4HYRTDwa&$98X$po2ehTY6qmVz@n)#6wbvmvW+MxkYbSgC<`Q=20v!RiA<( z*XUw>TJxjq6}p=55-Vg4ij+B$P|AzTty7D#=aVUei3R-`j0;U&iI~thQ-6uarBBVX zX1LYdEFfw0qX{n`l&D7?Y&yo&MSj;$GF2xksE_Op9d~%6F2s_p?y*tOU%?-9=-(+} zTYs?R)A`MxIv&4C{}#3&UC11#Fjn%4O1Q3(U07>(LH9n?tQ&Y+X&=NSB)o4PwGLc- z=IKzP45Z%|-zBkwtiCBI8UN_;oAOULHC#Fw);`~*C^w%6XwAw#DDKXXCU5S>keQOn zrEphgw;p8lU85Zj^Sx|C0(txdjSF275669)|CEv@U{~MzP=$XMgwW)Boyu$vZyB%d z&oX!4UJZ5^XYZ<s##pA!!cHrQDr&b*q>68ih;SN)Wq$mDmI%3?`#ADFc#fKSFXg}{ zkZ10R=g{np0ODjKQb1@(bhnXYvm0+?X)DwC#;)4^1N5<<U(ub*%1UB%RX{#`8}s%7 zFE3~}sdmpZw#8-leG6nP)@b5d()?gv{pSSB?%5>SFi~O?`90_>G=_SVl9KZ6oHuSm z6*D>yfi9o|y0#Pc-J`x8{m<BavnuDj?HffuL<`K0MsP_xmIj0N&Zt8_tbLDD;t~-T zSJpc9;}Mg5zX?E2?{!-CMjt03)M5^rZtf2o*=4Ljj@=W{?pt&_3uuj}*<abrxKs9a z$#&=*K&rUbcRB25{rs|knO|TQudl-4R8H7z>_(Qwb{98hjXhe4<KUy*78R)36cHUA z-S_ntHa?H%0|v-bQ`mUF9*quDP5iJ}fW?lKElx~SP-xv=9g!L&knCkhr147+RF|1? zx$;CBIvmX<u0oV9&D^7zD8z59TTB^z+cpV@Z7Kv>&n~YjYE#8`g^%>r{KA$7NKDHC z2VC5|o+TSD=9zrnBeLN%zPkkR13T?lxDRyP-jr_eX9%=j&U+@VYI9UsxODym5TiLI zcNYXM-+m7TD*i7WAZTATcp^?KPPgP1_PoBdm=PWiZp!az*i8$A-7g)%p%?+%x%`}* z+r@{LLu%+~0n#H+@0{nt+4>?HXsXY-n41~)NiMENeXH}69j>GkAx_IrH_p&Gq+4(8 zl5}mY+E)1m?sMI4#Y_jw^lZU6o90i1`)AqD%{=@9Mtqg4eV*N{N5P2GUq4c4lG{Az zw!7u1Pg8(airBt=!$lk>nU5v2*`fGeZ&zr}{k@m-*XFv|*fyf8IgmSyuja>(jCSgu z7xo){rD$d)YUbli*gPT{;smic$j;a}PuGuxR9uRt3KS~FNpn{H&C~4zOy7=o{3_gN z__z>lT|3_&ThQ@&kCC(-VnGHL@Kpo5rXf7%v@WXqDLE^fbr#h&`e55<j`LeQ?9wfJ zDqA|XSUo|*w<hA~J;2+kc<+Qc%c;(EP7QI@ywRXK`)&qnWrRoh<bu#P!)Os8X=7Qa znO(1$1^7utiL#M9d5WTE*~CV{bDGj?xdD$%*46edFFiW)zFZnLyHDKj7}n62ygIwZ zW10Jajq`-tLlxtziNEp`X&X{{?1JVPl&8YH(MRk1<;vCA7+964=`vN<TKcvl?UtRo zY21eff+FRVH}xyTSGif-LX+3y<m0d-0v0LH-UtV;0xytv+MjHP>2>Z~R<E{SRU|2< zdnKMaH*y}p5y|7j-@GK|FjkbR0yg`Pfz<MOAZYS!n!&{J%^NjoewPfCDn6!r4jz<X zb%9GzT6vb-j>(z~`)S`RWQPyWTvf)>1vT^IW76XZS(3=3cPXFccWk(aMP#za#0tAM z*q)?ytRzL7Uzlx1CC)s}_NDo)(D1X#X>A+vEZ?OMM#Ft*Qbl~D5Y(NIeL%6ct#<Cz z<xwKKVBJ?s+yKL*ijUjao4pZYCh_q5^fQ)IsKfVoA*xN@!KN~S=(-49OP6nOQUjaB z#m80eMk$Yc`K9A@_C|o7C|>}dt22?=iGOpW9xLM=Uu0drThXj~%kU9~h|9A>Il~q; zagrJ4ganAImGk2tsj1{aXoAQe;$vb`c2r*y2X>14=S2xyF9&NJE_t7?YY63>A1$7j zSFKtIC^Xc!&-+W4SCF44h;{N;WN~ed--sHKqm(CRUpwfm1pgRN$1pNBrYOtn9XF1| zIr#GF;a8bo=tA#z3Y89$INCP3NWnp<13`R%Ex!Qb%YKJ0^OP*iDWM?H1XHFewhSkN zKI?Ku;9?oze!Y}7y*V4DxF^8y92aX=`zPc_pjlr`YEnW1RY}sAGaI4c$BTEvu@dRR zqYk>o))xbt<Ux3~?Jl*uZ0ziWapTQDtku#)=W3<+QLUGr8dAFM5!f^YtMw5Ojq|pp z*VT2NzfHf)fj{yUYOTtx`N6CFOpNHGQHaTU3a;SC+<q9^U=E*yRwv-`QgeeWLCV)M zotS_-pRS7SKo)^^R)qp(@HKr%v;x;WZqKX86yJkLN4e@Y+VbP%>x0kk9LDMW5(wm% z5qs5(V<lSdn3P@bIM{XZMn}c5*VfZn$0ntFlGWc8SSQtNDozP2>2WF7PB(zw%Irrg z(um^=LHKeYX{PV2^SxT@K}Gwa!G1R{>*75N0h7%FQfi!SQ!T!q>CR^)$e=v<;2u++ zb$iyqVG_Icfknt21K`vvg*c{2SH9B0KEI-@R(TWi3AVBC4|2YIA$fX8MADE%;Y0e+ z#)%^$EbNWX`(si47AMkXA@|2(-M2KeV)gZXar$!!?L8OTkDYcmmqOGHHMw57+&>() z&an4c1UfA9PecP*Iv8a(h3IZ6+Q1@{qmyahsGZPEP}9(G)zmo31|7LZ$HXwc(RZ}d zLf}jf(cuB<7Q2Z`x%oXFBl$@t94_O7gM8#~!gQcVUq$>mGb(0&8hrT}>iYTf#gabQ z>A?}(FR|;B6W%P`cEs1B-e5HeqGjJ*9|ONl=4h)z3D{&?WztAe?e?<cVVu$2al)u8 z*5J8s%eCCmq4|Lo(G|A=ZmoryA1Rq{^Uue_ZRTFEzzu$8e&~kI`IyclCPX2-R?}N8 z(D~t18Ca{nw9{(nj4C*U#!QI>h@$`cIjg23q%n}BSkR|Bc17bQCwhLpYmo4D3_~XD zE<Rx}u}>nFvN%l07)1Rs8{i>2dd0%esSMrRY&NLCi{EV<qR1K5<qtcqS*#F1-vdB~ z&&8#s4`$&b%5Sxrdf9b{Td#35de(Ze68bds)j2F9avsgiX}=m@|FBx~zQX$|GS|3Y zxlhY;m&@T`D4d5J8;T#j*)5sKsn77BQAiVUbcA`(^$twougp)h%wcd+mX<dc;Rh7b zSCZ@tV?P8Ccnq*9@qT$^D(`cEi_QaxJ4W31X9mJ(n{Bn^=MzU;!8G1x^GLMDV#8WY zV{tEuZ`vw-uW!gF9-~y3n@3UWD~)sTbQipSt^B}}kGeztyi%MG=|xsxU*;2&b&&ea zp!ePzIk}cQelUHm=H=;%&r+2wzczJg=BWDkQ6I|z)&6vPQ`OuxH+`3bc@jy}0D~p> z>X(-W%hzC$qP@%6W(5Im2k2KhxO}sLF)le55NIvj)6oF}XxHe+n-YV$;b(~)Ik3;1 zVq$rGd9mX-l?f;d<Gr-~F=x9o@=iY|pAQH<O@Hy>!;Vp>ADvQ1(p^_0pv~j)?&dOU zWgl!HlTVp(Zd>kHpO%eh@pxs8a1&tMeGfcI4z56iKrcLxG%v$vP@++H$D-ySENe*X z3q3^R@Vy_q<4Ibhk?@snmC>4B<EW+gsfQ+J09z49_*F;8vT^fh2~JANG-7eVmM5@X zZ3|CE$Ymxb!PNUEv*+w0j;o1$vi<6oS;eJskr^ONb=!;aZMltve)I<-l+u(>owE12 ztz~G_@Ayu->eGt0cM#j$!D0FNP`^PS9WZRk`?A^KINt%|>wJK^(Rz?`WIrwQC6<%r zjQH|Nyl$iLIqK{QDqT8@rg5|Yyaw!T{BxGhP|y3+6hs5L)~hX)yuO-CnuqF|G8E;9 z0Spe|t)hG|3ayMr_uD2QB5-J~M9NpsH(KlMK||U&K2(JA_?i~XwOb>?f{AR03Z1o> zqmYa|{D0Vb%cv})u50wByQDi5P#Wn5>6Y%6lJ0IvLAo2HySq!eySqDXnsfPl=Y2n) zGtTgz!{NB@z1Lnf*P1g?=Q&-XT5alfUgykx@XBO7nUSGoORUPR=3#=KdhE~!KT*dH z;C%UT&4s$Oy9?ivxAV*grhfC7tqqwiL6QN$#@ZH$wI&wcSJ|qkhRL&aWt&oY{#!$G zwW<4yw*9_?$(}Z@8T)l8RJ@P;Zzm}8cL4rv2j-Ixq0VscviD&pL$`(;<K;%;h(~YC z;QUEx^^DRcJx>DB_Q3H|4VC<0wMB0_b^$6V;+?rSzh45&EbR84o^IwWv^zG0y8Zab zypHbT*#^p}8Oie5s&P(h>q@-SF+In^+VgNa0E#l40c<S`favk)PxH%mE%3_^&uT`G z%y0rHiLW-Vgit)LCk7EVFR%C`{m2~wX!a1%7sh;ldNJG{!2<U)v*;6L`x4|W(ma49 zG65CN*wfUl@^!sdxl^^7_%IF4XB*eI$6*&DKKbKrV3>jQn+&hJ{jpBGXMGDqeT$vy zyYQSZE=#PxOcrl^FW8CPV!gX1ahqQg%G>vFY|t83_1GC!t|Be8eZ-}Gk_|@qCRUw& z*eTFafqeXj8T}rO`}f6?`PZe;Zzd+8P-sNk&E~Q4GCYnaCo17}Vv&%GrvmDqD$?E1 zeD(Xb&sqbQS1bCC%aIG})$p$&|D--*{baN^*>5`NcIf?qV5F0}vv3cv7_+fa4N|}Q zC9zJ^F|_b<(e;O7(Uiz?+Lg&A8gQ_9Y7?dJrrrIjy`rHl=~Wm=J8kxh9!~eNDka+Z z)_fI)q|L#EwC}aKQ2DW7i^p&ZKVP)Yrowt5Mw?`eZqUG_+Kvl-(As<NkxApB|BU;j ze4W&X%jL(3&U-zer<ln6yJjhKOOq%yG1W*$@Lq3zeM-ahHM@_UpA20NnEyiPS_=QA zFl~)VNN8H5prZ0=r`Nb8eDQ@(_DYPFmUiBCXi08|pa*-4_#lUFKn8ruGjSVZR|*Wx zVBs;Ad>D8fMtJj2j)@)3`~uBF)#8AQg9E^x4QteF^s>;+E}ce^4|7g;g_6NPXKHzk z+{8_fb<54Fyq?$<zO~XsbRftpIXcE2thFUZ@u82zoLp|rL?v1p1^OEr%|gVuK=Qa~ zMqY!ROkB??^v@+Q0A;HZpcPD;$^hOHki+57b_x7bn;e{DZpvZ9?L303#X*lHFskz( z{DZ>-&ZK4)JrLkg)X{c0wfY4|kr>P(y|3pQp-~^xnoc>l`piO9XhA9Dp;5TH@`(}x zZ|?$_t3Y~)DXN%!I?pGpcqdo(nS38Ps$yH7S8wFO+%NI-$*=#JQ_G*+-7UngNn7vo z#4mlg-oLMn%d|8H`aoyyFL%pR`4*wfRE#Izc>5B2P_{6iQ`=g_BXz&Df79%+j!<uN z7oB#ap`j5q&fDiOmxU9%PdyFX;{z?>^Wj4-f-2u$+eE`iBdCLkSk+~o4C}}1KH1!G zSbn@Xbm_R2+*OKUvrui;wZHcpird&<j~iNWWLUPADaYh6;nw4+f>GOecxxr!k)~Sw zxj){2vhUOO_%7OvF5<|7fXnb;tsrS%+u(-%er(>5i07=rCzXQ4%}grwiYn77W*Y@m zEmQI#Q3F|-rpjD-gw>=7E%@7fl)-#q@zzq}TfLOF?PNP_1_m4|2FLo1DM0%C{)KxL z;524;k4^}Cc{)GUI8ZYn3iqXg{7yn?VQ;rd5L8S80`w{Jzg-m-#1;X(59&56>RxXz z$jnBMtn<f-eb*5Mb#rCA8EG9B4H>dJZPyXI%Z}|2>utjw7Pq}U^IpXzqb<|BFs=y? z#}!XC6^Rp$+H$}4YtV;NUo_UeXK#3#b`oKJtvqwUTt5-oxTDtc&rOe;A8uamPE8*> z849#8mOPv;bJ-yd33itGYSVzD#WS&WJi=|A?9L2IKVASRa}(d#_h1e^56#xMGY8dF zsD!siLQ?gNl85Tx1Rl34p*tET>58`3c8&UK-j>VDrl!TAF~UFo4i2RiJ>?2)=*(j; zZqZSg@a(9#oDNsJTMg@~PmbTY#KX1u$QWggMya7u5o!NIOr_io_V)3jmQLG=c)r*W zVPS}UE1BMA%@3OGo<&i5KRjh$V3BbOGT1fJ9Iujd0;+=Atj#^5+iTdhG<J7_)?_EL zAog_5cG-rgp9P*TWT($pisOf09@Aru-D64<0&jNI<-wA&lGl!EcTYO{@uMRf05~*& z;Fkp-N65Em-LbuypPDp1{v12cvL6XlL+UL{;I*%EI*qf_U^QL$ks>Adrj=Bc<~#1| zAc&Hemr=bA?^t6D;b7#-6&xwTpat#V)myl2f`ajT-Ed-`m}8qFhlb6qrhPpycX(ch z=llC}zj;fdtZX2qBTx;~k+4@}Q7QVfmCuTY31z+5ntf<~0$v|QulDOq#4;L5w7nqT z){cOPr6Q({ftpB~<Q?n%{d<ozb?yA)(&P=l@*1=~Lx66ZJ9l?XQlpJ|tGf}7!D8ji z!m$YdW(E6R2>g6plG$quZu$K2xziv+hU%xOxu0v*ls5z)%Z|pDJ-HlZ_HRZ<Nc%dw zFts_D8&+Sl2C|1XmDhcEX18BdPFw+GS_>yNCB?95G!;e9`!(V444`9WA5}{>2fH|S zPF$FQ@J#3mOyd*i^~~!&9XznH)oq<Otn5GX90}OAs_{X!r`;v|fsZ985~={Wyi<T5 zE|d#??LG8n2;4slSCwB0XscD1m92{sh9<CC*-`h=i_w<4NZNkg_>PSC*)fSx)YVJI z`qu;90FSdJxVcn<JIkY?{FlyIYo=+7w~NWxv*MqiJpKG<&uce!b{l*C@>06v^5ia7 z_&x`hLqlDgY*+e>-skJqzJ!*%ygZ=A5RWoBIj85fH`>tdyjp&q?9;Z@?Dqh0d0c<2 z1!Px4{tjB@da0b&S|mPvuF-pLr)ufgw^|=-P22%GsE0O_zeqaPy;q6p8Px+(NM;z- z3!G0{MR~$f-C;}BHy6Rf@xuWE6+uQIEUakAxi{=^3Dh=5Zc5P?+=`$eccmXQ%3l3g z!=bMPgivz?m?aM}?%=bhCv?AQ(O=zFr;AN{dSXLEBOTBW_VhHrqD!cuX(RBsG?DQ* z7pkVumv$e9uz#h`<Yaljj8<687VqMS-zQqR<ZkN?5)qF<I&*aSa4MXBNbs}eJ6m{9 zC(kmTf7x@DMP_q<@1xgD0Lh=qzH0TMAl*G}*-QD1>GEJOzYlyg+rzq^DpOMRRvo@& z==I98G0Jw>ZqrE5=kcdez?FA#eLwRoy-^9wO~DU60!;8SDNQml_9x+Uq8}#q?MbJH z<GFn$lRLlVLPS*kd8p?@wdMgv$wiv4&?RM5`;f%6DWPW68G@19#=o`-(S*2fY3pL` zQxDf1?4P#0^*dJHWmcHO=<~po&hG1viruQBqPgv><M2%c8b#-j*Vm%TESYhb_IvyM z-LZmn`%<78v}pTiKA;u!_<%b%Z~eEMxAV?rn<{OKJ!MhgdHj^W*jc^CB;9zjVb#8D zmtCG+ee~7m(3r#3p7V)p<6Trw*G{jWb4Q8&095!U8gu{D%m?T%3cx@udQqL=s>IUj zeV*yJ??o!wtuFEYdN_=ZY|yQ5YpI5-&2_p1OJyG8>mD#^<ezJ*Tlv>cd`CuzYAjE$ zow1V96hgwn>{;(N;eOdC%X3=hT#`<CMQ9rvkA?TV+|I8PMa*Y*|6MA$xu~;HP2S^) z#>XYx7h%Rw3L?_8iU+6~t?NFWT&b1ORJP_%<_2s1HCJGM#1y|+=NxW0fOUy%Kqr#G zXkB8uCfGr^)U(Nv>u!lo$E^?OJd*6nrf{y=cSPpP)vV;Z2c(6r(Kwy0bbVKn*jbJU z&}*7{I@fR3xj6`k#9c=GY1#95`4nl@P=f)X1FQv1)R}1ZVOv#+=#{JzJv7=0`<Zj~ z1oOQ8Sh*3={f2{!+pyS@o!zCbuptiIWx?B%#L1d5Uz1vDKm_t)jz=$sc#E|R+~XoP zANSHCp-GLa%1(S-tyBE|;K)sffrwnM>&hi{i>Jp;Wky~{{Tx_@j6inH?L4=?LFi?% z$_RJ(8W*e30u)6pD<@aQ%R#7#*m`?6lYl?Uzv|edGRl961K|ZThhu40MbfPC8~1Ip zm9~AcU2cDIw4ML^3{$3@X<bZb%Q;L%LqKa3$J+D6mAiH08RD>2cI9T!F+&6LG=M&$ zP1*Kjkq0k|&9-ToE}vS82&w^r$FVHg#4ZoU_4!50h>Nvkrs9pPL>6Lvz0M+$>Fm}@ zNz^#-{`p!S@WeHyJ~k)Ed%mi9x2GHvPPsH{=w`1!nrE#Iz>~!gotdG#?q~DM#-FGS zWn^R=E!d6rJR6=CPQR+EQqiy_PkOwyL&*rQ>Q641G}lBX<EPxMTwdD8k(hvgU;Nmn zrr~R_4%CuGq}@i|T|;*s?mbk6d+ohGG@TZ;vMMvic)J%k#($tkv$yRTu^COId<N>8 zHvXU5LY>7fOYuIh0u{p!SH3RmHQrx5_wcE?-HLq^od)|%wKA?p8*a@!8;~b{qQH@U z*OR}zys5qRkJVxOi*dw;RU*A-8+AXaT(x_(jKw@n&U=2Aqfia7?qg$P>rW&+&p@|X zsT?zdcb&eCId7A+hk@V{dx=vTf7j$KN1(2%yEj@CP+c*b_*QCp9?Tj}!ZPQyEnv9- zUr{bPcV2qF=jsI1XXlOAU3;VfcduCi)an@?@v=s#yF&bym5=r(!U_gn5?*Z&9|{e; zCUJ0G-U7zeEit;+tCkXA;PiW}8lGpb=;Q^itAUrlVtb)}OqjT{^E*p->Mx_PyEj*n zw)RT<rhYz8-B8-y;BlG#o%c%psOQJj!?Cc>yY>#zN!{jCqAor7<!yUY5~YUaT)lrS zz7;apGJ#eRzj;;B!w8K}d$)*>#sh5aW1U0z;{=6_8ui(vUoEG6?3(fAO6>ddc`WQ5 z>4ug~NIK5yF<<iq+4+t+n(vPvz4-uTB#)Mh4@XPd?Xj`&DB)HQ+S)tDj^}3e`juAZ zp_7IF*5x-hz3t_!*Enf2st+HM`YX*gfeC-?<czu0Fo$5xWar~RxSD0hEMiix6Ru&U zrHF=lUWr(g0suVbe?9Xco&O+Z+Wk?zVKUhtD~^J28K{Y5q%$5jf95}^CIckTtgDXq zy(}`<Q0W@V-}rya_1mpA6~J;6iI2Ge%{=u4rEJM@o?(#J!o{E5aZQrh3O$=)D@(!u zvH$h$A$$Fix{Ad6Z8R2oG?YD05KlOpR=Sj^Xka;^tXof$-L`v0*r^S2Fz0RU;MRt4 zzlT$r3fR2@5n*a9Ir$D#sNQ0J&Dj1Kf!bqcwBz#g-z}nsb??*W%Qy31M8#E%d^Z!Z zTL2&IN}|EFoOgEXeN0El)fHlD8)S_nI}QqwqwnG1PU%};pPvUeCE+)T41^Wu7N_y( zmh;xZnlHGw?M5JwAV?ArQfFPH{q#wp^==3=pV5c<`gkcXmP+l=4e#{o#Dghtds?%_ z0F*IYw0OO+J<djd-?=F)b3OX`&6*`HdtwyY+GMxrPm9wKR6-xW>suKBsjOY>Y`bU# zx$Nsi0{Ou#3U~$l+xWoCJ(WXHgQOD{nic(`JTo2^LR=HR>v>C8Ma6vO_X+wU)oS~0 z7-(_P4WcbH+Ua~f*5_$GV^P3+e@TeHDq(ewPZp3ZbzHqsRaFjQY`_0)zGB?WY}rW{ zXb<I!u3(b*;qm5>78dQ&`zjwGMGv(xmE+j6ugpv}m@6d>^d$DW!Ptt6l{do_?rKKa z0@4&RXRK3Ot0$kkF)02c8n+E7a=zbFkUye8*|-R8E>UY(mzMkM&KU(RM;hn6x1}!b zrr;AD1^0LoO)_-B@9^|d&{LSepZku7&3@Udl9rBUo^uC}MK9yE)^o;Quj{>0eUp&N z$_c8Mn^HUuK;_i2#n~Fea=I7-Ds*mk_B-X8@lLr`hl(S;>-sbeVV|0w8|)8?wRPu# zOp*D}h$L)-m4(gLm$}kMNZ4LYT88eF*=~kc@n2~>It8<|u`y#`fa1+H(GS9=PD*Hq z#~^nIlRB`bmiMaQEudljrF1eRpR|fp&+R_C<64DKvBC1e{eGiO4Q9XJ0`1HE88jUJ z!bF-|epp_|(~W~0tOrzL*3r!5WOVV+djk<cG{|qDiGb<=2UalCn$Y$^v<SdXNN|q$ zh!zs4!&5I<CYOrnh~L}trkN<6IMozuCND3a#A!zZU5gyYmRFHUI+E;xx%^EhfL@E; z_v=O7R?ZiVtI`Sci4B8^<UDz0&0kDlu!Ct}$1}p<)5Ct5FC$l8V<R*ql-AH;u{&vY z9FTX}S2GhvL~VTiGe3DO=v2s!I5Id2mp#4JST-z3^D*vMahM#?5^@k-&LgntxR#Id zz9h40xI108^PB%2?$R27Qj8_-(_kCj>e0%TJm6Z_;rIy?78Qs6@e*|^`*WyH_PfuZ zBy#pY!ximN<NPnSnD1Px8I3`BpIrrG?droQ1rSVcDsLyRO%)WFpX55<bPV_Jb`u^_ z{YUC8H7P>MtFManQ@whm8Tlc=s~)LdDlbp$n=eP}TALC0uf!UDn1^Nzkp1UOqkTQf zOB=Y(EODzNY+8lk_#7IAlDChvYB#H#xyL&IUn-|jXOqJfuq|>VFhaltNI&Yr#>YQ{ zN!)k{)j#F$F95B&3OLGCAKuM{o9m@xUgCvkT2a68@sLr;4=f?j&=-Ux6D3qE?{y9p zl@HH%PxHcvT+r>ON4rzItXFgBA~yuLFf=S0-BngLXs|qG6KvCY%5*QA4#Lft9P^Xd z3OvToy1}udwnxu*Jei1w=OpjbsBqxQ)ceoLD@{&Kgp$SBLhzGH?>O>oGD-aLCd~lN zR}x;D1*_*q41X&V%Rl2ChGKOR)D&b=zQ~{)*Kn(wt1EU@KRwfmqM{&&{U7oc1L5hv zn=*{^j8n$R*}J0kQ0)ole|WX@H8&}1*)ex?!EBS%TCa-TX<lF18$48#>dy{kX8oRN zVqC1IeyMw}3o}u((J#QwEoLiK)kxqUplpfmu&iuHF#MA{-c!{PB^cEb%ZfvIyLh*o za1HnEfpn4P^>)w)@vdz%h<{_>!jjcZX!nGmHTlv4kXChOLs@Ts9$H4B)jpW^g=mxQ zAjlrw=+ErHoFQJ_3!JK0by(l_-wyxI>CP(Yc=SGa#I$xpiPP>4w*BalJNxF>EwQ&( z4fU(wcJbqQ!@5a(X9%9WXyJ!Ue(D*KTanIM=szI+De>vF)ln8DN%@vein}W~)$0p0 z2t$VPv2v)2U^U(Nebv1aZN+V?d8oMx9fVnKZSkln@!>lP>I#}PIk~NHDxR%+Jo|Sx zMoQ&Mf`Uapa4jxK9#adBvyY~>AzZCtwYmiaS8rDf*ZzhS6idQScUCaVqZ3SqKQ4mQ z%Hcre+a(o=VGR2+SGNnFa?+8lc~glPi~ZtCnqKr<$LW>De&NvpA4>tfH}=M7QzFo! zO0AsmcEfBFn=EgX>HdhVn_l&<VkYT@feZFE{A5PK7Nw%~u3TSh8@6hn)gkCESSsQ+ z`jOXp#I}p!m;>)^-C1b2&<`FSoeatsgqK?q03{r*nmzc8@Z`)^RHL#n2;dS+X{_2! zIp?3stz-=aXp?AxVrh6`@b2ALf*CaV31)BqMQJzDKw+A*^^U~ldr|?0@zI5BNi5{z ziNm45B<c}_{+u8kNv393w<$JI)A&Zqxmt)bpS{GJ;IACSMYgk5de1kv+Z0)6zTGyj zJ(~&y=U$}+0Rj68{gz1-pXVMOy7!@#9IMA~-g?nt=WUE98dZkLl{_sulFCO!L?b@? zM16#Id{Sl_v$JfsT@HlchfS^5{r5YQ%*IPw{S-3S57&%==VQ4s2$vSJxwM%SaA?mX zYC3w<3EZ{qu_GLSz(T^JQl@pL=ZCaGgFY#{3V1Kp-x?vlp8<#ZwO_hnZH+=t-BHQk zG^g>jTaTn?SzK@c-YGYGi&&J!OTj#RXQ_^Rq2B3z!)BW+bDmwz#=iAxvxCclkx?+> z9dmKlxBv);t`+7H+#*zuh<9&$oqtOdd{g_gdf;&OQi}Y|3ASzz7cnmM>iXJ&oP$HU ztVlVkCv#8;ri+343r)=Z88NMF!`_15OO}P&CMOJd?M<zZ+vjl+oMV*Xb|g<nD^qDk z`kufJ>N#?s1Uvn4^v(0b(pn?)Vcf+nIx;K{jtR;3%T-=CECQu2S_Hn?rP~;<H=}PT zrZ`9PnctI*jiPCZL`R%~hs984B>$^_p{_Vu>U5<mr^0;;DZ@b^?yeqfH3T{fp5;2l zncKJ6?0NZCu@B0Kh_x@?<gARdm=LD$Q4pQ@?$%s)1ShL4!nV7s&9^&KP>9Z77kr}~ z$`nzlsB8&00D;~iRW6!lBvW`iJRXrdyfSV>oPY-;Yrn&3)0%^|t5;V2thPFfgr2Zn z0YN~{O0}4azM;GxwVe5VAdc|~=jNYvm6M~Ps@&k(q&b6RdaWzCkB;hDNNBwhTZV2k zfDAEY;{%&?m&c?)#hdC^V#@Njh`?|Ho(4OWfbl`<K)zlA$C=BXWTmZn%=|Ui65*vZ zelK0yl_E?YnB^PGPFGUHuBF%8bF>>}ar^Rs;9m%LP1|=tF5P;b8S5dGI2B*MHjbgJ zdpBsaMwq#}YPp`LCpyhZc{Vq!yJPhFYa0gTg9V-ywc+JU7UCgpmYVFATr(6N)vT7t zEJ4^ULs=d9tnV?R<OSCNKIE&y0z~NN=NFZzob-^AkvvUHr2t^~Q)xfcyeRRwJ_+?# zZ91=A91HYEd_v;Ycot~nMxpz)@^@}hkB^V{-K`G|o#FTn5Z6ybpRjj#EA9K_E8S-m z8^6cgBP+V&nnj5k-Xw*FYp|>pO*&BW^Z#lX{Ueo)3?p{*ZLg`tne<aJNpr_|I*V*= zq;3TMVX$aH3fB|rq;pk2i>V?RC8bI!5`5ktOyb`Pxp54@8q&pZG$!gOzrmGk&NjRC zy<DwMWdF_2(46Tca)5#!CQ$Cj`u)7aEdV4RYQME#5*E2)M?4YUHc5}zP8Qj;o8$0a z-UsA(-F){vnS3(1q_Er8OT-(<y)!l4M`YM7VO)b{{Z6346i5ZjgH1DSir|q8ACc`& zp$`jr)qa{Pq{J~r{?%m7?R|8XmV@RIj1V>~8VSUK)S1jAt!pX^cQGH3edCRxPxy2S z)`@aN?{9DSu)lKjglk-P_6Wab`b!_0S9-tD0Q4{B6w@o%^GRcM#YLR<H_&&xy-Hu# zesS6*N_P3p=+gkiyzv(a62+gD@3!AwkVxDwz(I!*<@<_+Yo>3n&C`!4gj~{!ut%GR z<|~QLX<A`042FUySc7%&PMti*W`gK6P&NlhXs?@c*(RgMm%XZ%+m6HMBUMe7$X`xG z7H}LLVtwt5hv#%6`jYQh^5^5i_%82_(D2R>F3y%2yJCG_az75By@A={xG>CI?h6-l zuJXcDastvVdpk-1fP28I(UyF4P{WK9gDJ@O+2*DHU_YT|$f<*!VC><#fSi#->uUrc zNbVO|VT+~L<yV@Wvr+|eH2hpP14sd&0Y?PL-vJcAcXuX)Z=y^NbDs5=YOkWJLkv5C zfk)a(c+B=hAuuy6PkZab()awiM;*2dWEb&j>wcxBM3eEnU~orggWhnYKRu0%kkPSf zc2v5ZvLp1->tMlAn$$4YX-k?jp8M?yRdFm%1Sj<vy^8xCKJBb%wa$?5#j`_XS7K%d z<tOn|R6JJslU^LY*m@gWAe7h3N$sS|aQ7^G9p{raJ$4Gd(#mwSypXTinUwV|V19a+ zDt-gaM8iZj)^cDHI?Bc3|FRv(k@iJ<NRij)`t-8`zS#sO(#|LDg)T9fC+b@lr>j~m zqByyp5Z}wck^Py)EX!~9%8^vy6)7$betnvh-!oiT3?%-3g2UIm8;x3?Bp9F*ukH+T zs;>Qcxb~9;`sQ$1Pt~VNPFHu0$z^Sn$>I*O{?dha^mk1Lu_5=-<X-9V@dd_q=kl`n z*V)yU`V?+kN*WS8Ji0;wwhPPym!1!=uq{iUVh8LC#tpf0Pn&sO?xrKxePah)B!;4M zTYg9B@x;Z&`KR$7^VBoKRkhUE@5e6NTm$i9?2`(~!>|J#Qvr9f@g8HVxMTAnhnz1I z!lNksdX*Rc1<YuTTD97`-5sec*!yv0+12TLAF|GJ{d4cKs<w8wmd)Le!Fv;_*9J%> zs4dt=t%i>}37D9eqodT+l-Y3@GUeToFSnwSsOGru44yd$DhU3}!aUucVM7&tf)fee z+1cxv%$3aXDvX9tN(SMBWbPbGT?N4UTe_XKu3umxKvG)-%13eavJ!f1M|^w_Iz7X~ zQrWe?e@K&t1c4I5CFdNI3^AtR#KdU@RD>gAl3Dh<PPmXnR==ELOG-;)hZ~XAvOis# zc%RGY4`RF@sELK&9DQ4B<LT6Z3LrTteMP?2@8u9rz3}#&l|8x`&P@P!Qp*wbc}ZsS zNiRis37+gwJ#uMP0hw+TrY*|(*w)@|w7^SdjS}Lo0X$^R0U$wyd0HUI@VS(|HyET@ z7BBEQ3l#w2GUWdpIwV?*o|Yeq*HjJ>*$zL%Y~pgi4aYcrSi}`5G<il({}U?KY9Ao9 zdmr}oYtJWCScjcd;q&JD(<f<bZ-s(;of3!u&Buqw?>RXgnT%<&Yfv7}Lr-9GuuZnM zac(nm?8)Oc+8Y!rw3)d+pS>ANuN5X(LQwSShLEv{(TNPwgh~(=6w5~}Am9^g{y{$d zM;i~s`wXOb;LQfK*+DsokEilrl6c>HyS|djcejC8AcTW@?R(Oj<f&LY)^1-RFVTiH zE_k(sggdMA1Z)qlEu9nv;QCSbkRgCwr`V&RI{6gV2<gN9_t(-rdD7-9{coMGt{PWm zOGR?|a6vDR7h?jtndmf6;8RHCD9OG$gg-A^Kf#@LM$InZ@3V?MUKeX6X(OcV@wi>Y zP<STa;Ps~M_aqHE*_!NNGQ9RM<ZQy@eZk+;=|4hU+rQUq(!kU8df~eV<jB*~n+NZ+ zdrSqL<#b~o`?2w4P;Tqc%;p;-r^Y*4ocO7)e~!P>ayjmoL%TjEt5H5BXZMUY@McM% z6m7(X{lK5Vj{w;t=GV0*Rg+FJlKikU>VrZUiVpUo3MU;LY_atgfQEq?BA^1>WYHOP zIDe@apETN+MC~d8nd$SnaFa0Y77@TikeXHY`DC6h1C`_v7Mps6xg;zGQ=DMU-09;G zk3XxjEI65$w>2OSm*@M92o5Oh?S>FHAw3?^WvxoWF@mef?P7$5G3<`n!{`YWgUPV> zfa<&TN+qmRGA>9D0TI=2FxF<r;$7)-qaE?}M>BUAqlF6vIxBhVF1rZA&z~8(*6wv8 zO1O-KW2IE9EDyn+vk65#e_nv0-RfIn7UvkV)*n!CTiK;En%0GG4_p8pJAEpIlcfZx z;|C32s1&~!s_yf?kHK;MDoP-NX9|l4&5Fyp6_aaJD~f+x5^6eZHCE6P+)*#%reP7> zsZ+I2WWj#L+p*Vz&j#+(_bzZxP+zt0H?;0Q7(*SN<H>Ix3k~N{S(a=B@4z;`f8>ab ze|G!+UiWMv;(s$l*f<YN^Y?o>YqTQgz33$N&495VE?-5cyx4o%akiO4lNXt!Z?;>! zxOQ$lJ`><5SKVc??%#>)-~%(>-^beQI;yOQOTf{ycNVT(zF*F=TAmBL>Gk!uc?G|} zKRV9b7{Wfp;{dwmw)5#6J$fWfk@&T3SflZYY9LKL^3a0?5>!fS<=^vFMv@o!PcF4P z1GCkwpT4?wc(-kM-!<Ik2eM#~2By9ZNp1Eph;|pUU@%1i?g;tEy6bmdJoEXnC0LO5 zbfE%fXDs!fg$<!LGCJjqK>Xd-i>>3R3~&5(&2oKofp&>kKz7_9`ru)e(CQ~L3PK>l z$&Rjdm)Z02e3@ZWU`ZB0)-=&3&e$ZZp<jc%P~#D-@6+nssa9$Y>SPNH47{Q*lU!}Q zR1%e^$3!~`oSMoPOQQ0ZQB~-Y(?&!>lF5&+o9Xh{x7QxO)yB4_>)~0;+K=-k(MeRS zTh-@j&iZpe?rXj49+z%6oNXFuEhn$ihYU=pJygrR&!bvyGZmm~Jk%|+&N&ss1L?Y7 zB8=Tr7UNmWd}sM}ePjjd<YEp8P)8R(F%r?JbAP`A?!;`CiSU!%?PZV7MP8c)gTXL9 z0s>sCqE8chdRS;|n&BWF2&PG>8h2YZ!XZA7`Wj$E80qlBzzf^zRbfsb!$Yx(Z6!Zo zQsCv~p~7AQ_{(#DT9_3C5A78bjp0s-*P4C09l7IO>sN>BnkKGZ_BT#9%H<Eu-@6Wa z6pf#MnCGOvy*z={?XM$`@8aF)MZ%(a8swYon8Pz0Cs^SpDD}=q1sF&;N*ghHFga`D zuxUALxex0e2Am>^J3uC*ZNui!W?!SX!|2#BUah%X9uiZ8OPqNZ6KM_>H@*X&TmX)l zPdxd%M%!cfwAFPa(ztO3>^*pAr3p#S!EBm)<Zx5~_DR_5U}ybsKnPMs1ZZJUx#K}V zg8OBE=UA$2fqQ4ygU=SSQJ`V2Y(ny&+n=Y_^O}>YSJeX5Q6JpgR;c*A$K__{)Rnb+ z2UqGWQt6U+u{-+cqS!jWq?d>FmUecAHa_6eA|SMY0=O0JY#@{BkvoWh=HDz6deR=6 z(^uNr%v>b5`*9yQUP=e5iTqrL<$i+%|3U`gO+UEIYL&xBhqu?Bl^RY*^$esIoT0vR z*&Ro8siK0uG|fM8&C5R1IZt&-bGFHWfqg62Phdh)g5qJH^~a>?_l)a!@>LkQ`?g|i z@5%MU(WJnpJD6Ebbre9{DEq@r*5Kwapj5-fl)fi?ceV;)Y#A_9;8LsPz;|~bEEmCH zSUJ_wWyoz}qPxd_DjrFMb4;}q1VM25*p(oAEc(P|U5lo<&^U_Ce=T|fHk?-jWMU|q zTkr2V3oDThJ}xcxMvSIR`#{dP^SZ2Ge*_!5P45wZ4~>hv9%iJ@a=7{Wm1Q(@=l46} zi?~v)NCos+Cp-tEd7JI8U%$dnt_BGwCSiP4wQk*?ieRyZYW4OVm#B#83`fIAhwEyE zSu)m{u%PE0-!cCQQ$TCv<5QvIaEh+_=6x-EW-}z9=Pn%;fb+L!!N9=?JI30aCdEH| z=zqv_ONYjP!^%;ioPfsXl+zUAn*x2XoSDKZsfr0n*~cY&6sLL<Ct>wlIfLZI%QL;h zW=?&)#x#~oSkS4iy3;Bcm8vs^ZJ5#sjWq*JKuuYqW$-$pMoNcyxL03K6Bf2h0;lIo z>B&-)3hQ>@f_hEegZYKW_j<OYvhh<F{t+*`=hag*2-t(E9Nt%e;*dzGU>y;UZ#f*M zrb)k(=|;wNv+vC;pThc=?JttHfy!gfy+@D0d9(}sY;ORx2{S={z4^1=$YoM<45#@r zW}e>~qJOi84wN}73^P0Sx99C|Twu@1iA2YvaH``T!MLQ)SUzg&?oXJqd$wX9^Up<A zCpxJ)%<`um-l37~@+R447!Su2Cwxr*`G^UTi|`d)FgLTa;@ZR2RWOx(>QG!Jr`(e5 z^|fI@<FNy@_!7v?4~|q*=PsekHkqDfRBucIpEa^{UBjZ`LqtcX6YCxWBp+CrnghKz zzJMwjdot!UE@Wf>;ZJ%zeYgZRa;ki_*t#XPlaS>d#R55ix9cR1ecn6tMi&Ya=ssV} zVEX)Ma_FsyzmSap9}Ad1EWd#-Ia2a&wo}zgnuV%fHmbx)fp!B?%YLiX6UjZ=PxoJX zb7h+Dj^~Iz_dUd@Fdo8aKN;JfG5B9^v>H7Zx!+`Kk7_=b0CF^2LJ25a(ZT0_3H0&6 zy1&ul^0_DCdCg3cXNIkbPD7h+66#I;I{gNx<Kfg|yX4#xRH%3(@;i&Up`Q&Oq(3@Q zK;n@9O}BUpeSH&7B3-j2YZc@p=Jh;uu?+-X8sD+oL@0?SkbId5&sgUwMnWcFRmQHP z)yQ~svQYc1am9X~B!#Yo$j*@Dl+`V|1+|e_;8!J_?Q~opk+`_wu;Of76iR^1ehJrV z_@xgI@}9C?HkIk_JIwBg)k}9EtBxWVzee*?BU;n~rxHm|-CpCy+Ec^Hfudb=Q+1?| z1RJ|+>tmdt=92MVlM3xhvStVf&9AdFVWlINDdCDSQzxR!N4&2OrES$Us7V={0FHvk zN&nD0fSm30-3B%}jfgM&vshN2jm=?tG_>a+wi=etK*(LrY54+PC-Rr+{L#3!+NBhN z3w^zuzOcwhv|*e|Jlkn%>c%X<WWveLX<&U7jHs$Vc6AHUTq50<r)%|ADiUJYhJdWC zSw2_mY<*iN2RR2siJF+OgR4uNTN>~LFaJcxS_7OwmG02CHIWt9`?Im;Y?64STZTuJ zXU1%+l6n+ba1fWP{v-qwL_`q0FIf~a8&kV7n_{>Y=3|gGqiKAkt-NjD%1*9!9Tys0 zIOcI#BxO?hwd}QBUEvt4HUQLr^CbCO*K0ha-&w0yE6jj;kwI6t)`AMk=GTw$@z~*I z?izTdy+MwYkiY?;Lr@4phk!6_`5<eL9otO57h|h1B|7LiADviA@_Wr`U?kuPxZk*% zEi-5*l)FMkmfzpy#Tn~#azaH%PcpgwVS1uk1HUZ3czar{G@?pLho#;$X{s##Mx|}# zP4~%f^>-@1xw-kl<zVwJy)26i_ZJD*hou2*0_I~Om3a29BW*vlGQa=*3^K^_ztO1t zhE=vPVRv}Gnv8ynke=&%L0<mwp~(?HK*Z<&C@Lb-Jz?-3W|@#(JK)x0k=WCjn_gK_ zNeQGE0EZUvXKeDz>e2CKF~pG8cpqG01<nZ3#_sNe7WL1zo|adm0a>is$LELXs04SR z+Q<@CpdS<s(Wyd0RTl8icf142UNQ)YNE7+w@-_E^oI9d{$ZZ|5ePobmpYcSi8%tqH zEN-LRDO(|B<ayj|Y<l}xMw>5(5oo>DBe}!}*5M&h>m4R0NKeTo4TfGLOR{R~czaj} ziPPl{xh25;YbotUQ5E)Z=K?u8@v4gQZBOt!br1s>0q=($`9hu1U*r6ryCH+L78Ja{ zDgo36>7;M&>?59LzVOc5*fR7Dwg1>=^64_f8DLzJFT<FK#EV6sCTNv`=ixA(TP zIGtwE5i{Ds7bh!F5y)1OIQ%)s@f4>AAM%T+tB1Shxr=jucvDR38&H2Y&F+!<h^N$G z{Z<C-f$V>cV<iCO21?rC@^I6-W>sNm2KGg|E6D@MO5?9kp4(rjj|!4G%?WTTQK9BF zs`SU4=z!&n076*Qgt{L&-L!xL<aqU?lv8nWGa_xmTc_f$x<F>5KAjDPIq3eDBeitG z;rbXjP(GAqrLEmICF^}SMgWJ6riI3M5bV!vwEsE<5kX(yU?0KdeVC;}O=?IXq3jbZ z^@2g<6e{m??}OzATxe+c0xgSD&8_TjjrMujHumc3w9W;5h!-L&BYA4)?Xokp4D^2F z!a-1C8;LaY<+D|oPsX;Y0Zs|=@j{AIcAdv?f0RmH;nPr!+&h65v!Sr;Bn}o4B#Y@N z=4@U#j9lv(u>u@FL(Hn6V;65k-ib>r;y))9;(Lr~HrK49XQ5Z>>}UGHRQLdLcqd_^ zz(v0C<xVtb_>)o5{uVex|Lmw+==y7C*sk=4rx3Z{2HV}K)=uh=uRmNR<mH`QTc`Y{ zO~+sa^aMnEfUY)~b&G=<50>nK;J)9;Fhz=+RtP|e=3sk2;rGa3U@+9Cd<3U;FKe=A zjAS8SjQRgQ=>J^cA4<S`H~nTk*_VR_5%xz#=_h$_f7?SPg?WATj!I8Qf<q$-iZ7X4 zZmx`7emD_P<y~DVPhTddrY`Xg*I45;1OclezI-h%c-7Fz=plZPyEroVAw^K5nkH49 zVQXt!c8FVB^@85I)&Z1_B@kpB9E5<BG(lz7e_vd=_}>iEHUG>EBzW@h026Zqhlbx} zzvO~*>XIzlw?2@wom%vf83fSO+A<u})zt+tW}8;<PqerQXt<{dxWIZpi1KRr(h1Qx zU;W3I<kiTPYG1yWwp)mEQ8$BceD)$DS?lWy^i>ls{J*aTFrG$s2mtcjc!+@zd?v3o zUq<Z@PbOPJ;BaUxViCq4b+j6GOi*$@Um9yA9og?<aypVR!^it*ir|Y6D<xwa%nP*J zd;3wbXYrMo4J~1^x6aSc6YM}V>N3G!aBO4#`|>R?0T`%j95<k}&iuVijag-Jv7Fw3 z|BBA1s7woDuF+IR5*`rtO079x92Ra-af!A;nP#0IK$|ppl#$?$fl9PMTVk^<=k48Y zJHF~7*zwv%$T90vUS=!=J^zY)Ja1E6q4d~4Fpq08hJ}`88mpnGJ+eUPLa9GAgO84f z_f07nyx;fplPwdoU&E;C;o+kHV6^FdWrST|W>Pjq#iSFwnmX=(`C5@Ia^QGace0<T zTMLK?Xh=eJT=E=~Dgm5Vm|-Akcy(T$S6^ql)0&%3T(uQ)Cbzjcg~zYI)<H_TLYHr2 zvV*tK5pQR2x2I;jy%&;--N`NSz09Cf5HwEbMa(Y<WIo;$mYxavnBj$XD@-h`9qGFs z)H6IdP>tL-W8<MM;q?D<G^NsjmB0${_z3vGBO|h_BfS(b($fc)sFe_<H0pIgpij3Y z9;mmfbpXx!9IqL(@WVN%M-;q|(leLa;+u|Fk{VuwE{_`l9G%0{C3bZ=;{c)&P|^M> zG>Lao+6(f1iGC@Lm+r!N5BDoki{gE*K9h9GN0kJ|C!uJDzm^#khah;w5xNxmf4!f+ z7bM9mgjHt4>*vxINZwIrXCu?T*~A2H5?kc+k%D|3UjVB@VrX-_-kT_K(fjkK5js9T z-v5Qj>H<JMuW{-8oi|U7e@aMkqhizbWyicj-#{a6eWTjIhBuY|_6<6mfRCu&GF0gU zA{Wgkq9<LiY#5|JiRopdMOU@vEaWuJC54)SYKZ!)&G9*2_XL+=fjkL{n7wwk;%Buc z|0i(&=bax&W;JERPHM{{)LvXzY97L}jb)%FGNbt$OLy$crS{p%rg*+bCS}$v{kc^S zq+m(Q52JMIo-Cq96_+CExR?{!UYxDB>uP<?AFYv$4{-%vc8L47iSW@ervt7@I{!R> z$ChVglrs^OzVvturEBk=D<hmuN!a<Xw}uXpNCvo@08*o$IP}PKolDcXsRFPwn6$*) zBAxz$Ke25V2#0%JQ4UZ^>FusoT+>b+%KSavTpL~jaWm>sR9^Od);tHzlmE1r%W)?_ z<nIEb!oR1l4Z^y)9B`zDgxVA-y{UVD%*@S(vMCY%>vusIm2?ozkop(7v0>WQmF_9B zdI}2JDJR2;(-3+<IKqqzEx2t<(sH+xWX9r&qSW6hv_t2S;O!%l)9uSCIyWqO$;oME zo!otHVxc?hnx(q+#Lo15X4k9x?qoJ%woXojO7bkKm_LE-8%zDGyGV&TE2o+WU~c+I z1GlZ6m4<{nE{uZoqp)_PU+<_H#)Lw>#e}Qn{Cov=ZFpEIo)%YX-ptVl_`n;?tcQQh zD~k`}3N(?yJemdNmy`45OiEBzHsZk2^&Q`7zebMN3E_)+lo;<VTB6;&&wRO6rOE7P zv$gQIOqKMJ*j)iW$BH(@lr~Z<9^c(ou$|^>VB9s)(>r{ZKg>USl9(}#$MN62bAKU# zaCpI`4TXEBEG?{Fa#0+Vq&p+_H|6`kA$~-}*Qdac3Plo^BFne4I9@<#=%FU(JtU;2 zeX5i|sH1<QLOQ?EuR=OYI{mIaCK4ezXZCsAfQ?J+CRpFsmw1@f?Nn*&Rl+xK1#7iI z?^JJHBrSHEsFV48tL5Y87bt*!3!evrN-l+J364;${64zrxj^DBb~(F#jtdR4>H4d{ zKei0mR2B!sYkJt4=7guUXy+oxSFsY6RPG1Lv6{4#QR-7utIPDuLO+)Li(M{_3cIyB z)G{GVs>N9sDN&_dki{bu+6p~eUh(Mx1lhMr+iw)9)M9dS2|E`6OxlxFg_&}5{m3?< zm&(5Ne0_c8jRLK)EE2?my#uj<%ts*o@4@Js01!6Q^|YPB>JIcT2j|1xUE`I#N^Oc$ z-GLAZ>lz#Bnt}AknusFhL49Vpi<yqv(pt&+z0rH6yV*fodhrI&wqZW-O8H|PFbI_x z?_VLC>WtFL{D_7JUt<jYxQx+&y|u+&QqF-mvm}@oI`tv$pOg;>UVq30$q$SLa~O`^ z*|JNdzOw?fZ2Mq#Vi7kuY+flA4d+XBQB_pByPi`Jv>~FF)QjETF?ukUZbx-hU0e?6 zeZr?Gv7tn|2@#9w5*8Eu_RVyX`5>apd972CE#$7GtjvJnO(68nuKqG*L>*;pOnCbr z(-edb@m+)d10`s)#hQ5r&7jSRMw`HB=e{;GgR~N)YIz+Q>k5wt`fUgb2iP>tiAO(@ zU3TiK*SIIwet(zx#$p=7w*H(O<3yIe^wpht?$|H+^Z!p|ZoIo@+daBzgq(2QY<%dS zKDfD=>6fkMuP`B8=!JUvc8kqDnD`lljF+W%A)tYzP^F}zf;}K`n`6}V81)7q*(x&< zB5@vPZ`m3SpFttds$VhxF>7sqpxLRt#jI(8Ax6S_CLdx70jV|!>m2QdmbICcVx<oZ zzgK{2t)?~4u!_M*C<r)lMfqJ+fary4g(eNB+IG;&igw>K;qcc-d>e{J<0dg!P=n`L zt=a!tYiHSC=)R1EgB}M#CY@c0J!DKlC(CF6e(|L$cSgsD+(6MBA+Wzl;r#fR_M_N_ zSb)AyQII*uSj>^)`dYJ-MM&70=9@+&hqVVf!+YsKl4o<&|NYPZ767O4K&g4U5c3TJ zQf!qC70m|iy?6xXgjA#Z!o{TR?U4%LX_{=QTX3??-dx!PPY47J6fmHn@0TT~&gsYK zwP(2S&+sNg^K^(Pc_Rd+El<#aJw(z{t(GrY!9%lR&4q=nSd?2wD|5F(2$V<vT0fA@ zpn)s|1f;*Ow<f=KI4k9k*_vJ3K%JbPj^>s8)HjF93!4y=`pE7pyY_I6YiZ;3rlG1@ zewbEc%J}ymDh&+`1aFfPeehK2nwwwD6vHn}n@#Qiuk;ih;uGZKdGBx59OrrJtZjr6 zt8D-P{4i8^AqDZ_!wJS|K!k8`#5cDi+>pB#Rkh(|24fJX<H5&sPFgiFF);^17e*67 z3|hPow$u4ehB}S)l1lk3!ei=#-eZnHF2-_WM)!|7g!m>S0Jk+FKOpL4Q9ez1?EPZx zt8ucUQQX^S<yWS~(Vch0ssXXz+FI@b<#;-muI6Y(?1RPi2})2=@pA=l8LfrIF>6u| z{z$qD3o^-P8AWzj*j`pY%Dz6LH$bR(l6iBJm^0TOOJ0GTB7%hE##8|sjSb`9d|W*V z<TYJ)(er*b5Md<Mho#r?{L_kGopP1O3*M%H0Aqtt$ML7PcLXz+UU*DoID3qZFa(6G zKX^eus-Z3h=W5Q5Z4wH(bs{so7GS-YYt6_>453+Q$=>>lAbi#;VS#=oeGz80I2u&l z&*0$TB??KBe}6v+g9+wuI=sak_3k@HC(jm=O*1wxZ!brt_%EU#Y!pH-Kn>kEYOYe} z`Y6B~n9-rnd~+^P>5cHk{CX!%-REwR<JSJh9g~#N>Le-`>9by?E%VLcw0yP47DNJS zRQe-QeE9Go(c6;d>oHcn-GKp<tdJ_)GG|rhHxPQRu+@JRbE<!FynxJ%36n|vIy$bG z%FSHRd5Cm;JgxT+2h(v0r|qTrQcc)UxI4+aQyhRTiueBUu}b3YIaQSl*4GOmG{&K5 zaZ_-MT&33_ANr;_s#zcs7W-@_6JLD?%TslKJXD~>H^Gm{1DMm~qM&?=f)IR%0pN%K zd_?6(2(&lf`f)8~m&C8j1M|V@sx6trcEHGT@i?0NX21uEUQ<)kuKvt<0LB1D!NU;A zKOJ(4)Og;|e_&5$9zjRPnImAj*Wb2h-X&7jEwj{K-EpwL!pGxMd_41v^+Q#D-hP<> zAbxwan%IE$837d`Fu7*WPdQ2yt1`0bmh>C=B_3c4MwV!@MKv_+t#G_Km?ZpOTtePK zCVz;9^7!;b7#mjQ_YT(cBRxH{zG_O$zwtp({_n(UEc>{&ZpK>H+#qG7>$GZ-F$f+N z!GLh$A%=P!Z|8jE@I!%X8dof`+e6dInp<2UQTwO>YNPEYud=EXA^#OpIiM8JN6sp; z9OnY`S|Q^SrH|i#104{p!Zb_wYIHg!)?|4foarelhLaN00OR~=82L&CV`K>mSynB! z2Qyq@Zmwz0W+X&A`}@Zi>a=JdpnT&qNe<=yiKA}N2Z+ABaw)gPWo45x^~o?EQqUo> zxlbG9JqA<12}N5d^c=YcSbe_75$%ckUWNVqiS<+I9rVSl+8dOL%52zv6wk);xwrqy zif7ZR+tWkUF{&b^^^?g$r~hLS5dXDl-6-F83J9ta!PhxbaQ$<^z-@QZ{2gDoi0zJ* zb)lngO>3!$__X(1Zc8a?_+<!Nz}(*jm?xvNd2tu5PUTR#8$az5;D=>nd%lFml3gjh z{zdEo($mBlDfJDCdG_32xqNVxk!|bDIF9s`MLA-k5`w<Q%lh)qkNxYtJDngMVLC6? zf0%6ia`|P)qCGfu@rk~jzg^qgt;p9sNs1xD3agGTNeunG3l0`$uo-Hdi-v&Vb9yo5 zXQYMWR_hn4#?2sax^|%~uezS|b=Pa11rq9X!*OrOY+BHr*U5T?R>RaMTu%>;FXzm^ zpsH<fNl@`z6$%|s@E}eX>OigD<OQszmz<tno;!|CMf`Om=o-M5g`!1HANs%Uh?R1p z)TyO?K1Ee2!W%k8$ko;3C7)$d=HX#z<*LQ$7~%!)Il(&8=F==4{K}Dv^g{}3Sx*|+ zVSlxE&y0#o{!<H5hut>!p!XdyFi!*zUUy0Kiq8T6*#&ruzxBfzlTceN2lX5<ZyS#W zg3ls}6sSvlOA&ldX8^DskKZu-Aj)F?NdKXlGRLcOG7)C?<{FdzqXc55S#Sv*r?HTq zgW4CmW=F-;f6U%m^gpeH6~NWXWCgy`09^x_3~nfY$N-Uek;J#2VAPPi$!6w!55|Le z8{blMxeQ*^f`w1@F`qr|BA7f9Tvwnx+>)Hn1NYxx7P+|YW@FBoS^9wC3iY5coER_W zv2I}HQ{6d`d$3*82`J*mrqI_YK6y`%TV#uTSn{&9jnXpN{Yd}GK${3{>LWr1_kSH| z(%+0j<^m6B9loODtT~pr!p((&FQtj#N2ot7bfMZi)`#|YIyXWnDPAD<))rwx@Ig^f zc(ahr&dzp+ZVy({TT`d;CYOqQ^IBKP9dNL|zQv}n+1hpyGU=y`CV6C+H3*_8iu(bK z+ZY8UVz!3;MOWuq+>O137?gF&>~D>y9{<VgH}3u#zrP-Y3mXUvH<2mPaZ>{PN|*8! zF>U&jKfAfvqSEjIEypX|OxX}5_(DT7Wbo3gB37s=U@9W=0hyS+`n6_(kd?Jmoq;$+ zUM5J@N~gKMvJoLbqz}+^?@kycOu4aBgAz2^+ohr_^#A9YL^^NbKO#w=xgQr`<4bhT z&#T!w16u-h596bw%)5Jfwh9y|cz;kMV4+}p!)~VX2dAeofhkYXyFJpnj|`tHTJ9el zO!ZfnuyZQ?{rwkHa5)a9OPd^@gJ7W!p#D3iRpR}p#p5>{lIEW($TzBdakJB*$8WHO zHK^}{@O0NXMy$m)EsNCU<TT~7)8c$Q26R8a+}MeV&pGU^L62hPe=IFl&FB(B%K!2i z*vxNY{b6X%p2}v?Uv>Aub|heu^#6U}+W(p9xp1sdP4-~Pqox>HB_UXna+C_c@;OvY zF(YLG=!|x|>&pm@i`ea^Sd;i%0EK}jy3JB0wLPjx5;(=uz#SD8jqUb(pw#k<^LQH3 zxX$(phG&5Cop3M8`1crr4i@D92~sWHUrO78Omdn=%G%iNPVL@@a;-8K5;uR_me2N| z+*6~|gS3~M3jB7UvR>k{PNkGx04Mf3@O-PQtBX!RWqr^o@eB~f_^Fm@34cEdq`D$1 zf;TBYXE7ZQcK)m=zvZA&<Bku+pO!)8hmj=mx+?3>f3m`EYLz>A-te{s3-t+gB?pb> zrB=!+2axk9k}*~y;K~yJ`P6cm|2)iQysz|RS$PPolX@^KJMJD&kQv=!@o8yv3$=FX z>bOdEm-wIwTf4gxbGh--QkgMybnI1_3)FV?F8z>?XwxUzxPI?pxW)}gV01JrVYrNa zzVHH>;AS|zr$yI(bZk1Mc-*JQxHzmHE*!!vk4RnrM`&nhNZ6g$xD1+w0c^tJa^1kN zA$v7#g0j$mzD^_y17dS~PK@|4*BSca_pFYzh{*rL-dl!My*2;Cn@x91NePHFNQb0= zfOL0CcXyYxv@{|u-Ccqp-5t^$(*6H()T8JA-S_kId3D}+?Q6?kF>7Yl#Ajw1wT@Zn zQ5?1MPF2}8sNhIcy12Ts4r7wt>*MotW;><drObM&(AW(6bd?{b-8Wu_W(XtN2th{l z8V0@v;wnM*ZzW3=i$PNrd3wqg))rM&?Pa*`Dv!O(R&r)g?JmzNFP$z$Un7$LHaYlT z0IWKemBH?cxj9|Puq5%xT%|>v_1vk<<-{11Ym0%7>Kj`QV8=`0@e#3~)Vy*<IoV_9 zKYQWTs8wd$8CmM)l=2w6H3SAU+pbis0uI;}_m(jkD2E73XAIXAwTb)$!p6oHe3thQ z9%}7`I}FlwDic=I<#cdHO%tYYN_cKC_3ZE*5lwR+06~>Ho*zZLYQF&Ovc7kD2?Y)F zw)_ate8L9|^z^>{$rJ3Gv(=g$fS=bakUAAK->^)=%^g#N*hRfWGyVu3+?~rkVKLtb zadk#W;z|K}0dclB4<8p-+$`Xj?xio-f~p|>#|7#1BcZq@?uf9lv0;Q^QK_hZk|@?k zsCl7$K;012=-6*-5yx0|LT4@%xd4RT=|FRvp>h0%&svS|sHirUR^Mi6&_chqqRa(q z27Fh(L<T!zi-#M%K?TkF+U()IPtd)&=&3Gv$`=%gi`ep*7ZeZxEjjZ~?c@!o67GGm z-)>r1R@#h>y^rp1cH^H9z%m*eAJ;70%z6eCs&;|w6&IU5DvHEUjO^`|6ItCLBnX~0 zT{1lDUMYSIpgwE_wfVdjTzWNE&#^1;b{Cq$ox-cX0+|mV6hiK4-uf|V8iO%ws-;TY zKU_LopjQa)gihz2g)5TG`d4W7oRzLnSY>X9ZE~lOy|0gBi;GC^uM7$0k4^#n<klg~ zt(j@Tdz&}Vh`!3R8Ctu3QOXFepK8V1PQq+v*=^770w%C9M-kP^X(4)gDE;eI$`>?| zA`M+Q62r69C!Ybvpzl%!e>_AdVo0dOR3R2ZF;;s3qKTnw+{tfSSR?kqQ9fx)GEpV! zf1%UIq04SIb_$e0#XmXt^nT1y9H)`&fXdoy0lf{FWP1IW9H`NRn5nkNRr&nLaii%K z`C)1lKPe;#A5$aq;_`BW0Wut<H!0sf>jY&LPXY2$*31U%?*>ZFH{Vs9m+oeD$GS;T z0KZ|-^J2M|Sa<%a2&Ff}=MT%RloId`-0)Ad9Kc$%r}N#zm@n66z(tt}-i04ue$w$- z8DjxWfgWLN$(n;&F}*~|nh-T1O1Jb+)0>-H@Icmd4NevT50JogzWec@p&>?G9s_c6 zqTrgV5zgDA0(fi(IKWHpNK(`mOkbEENALa^M#LKHHVtLCvD%j6(qhEKCugBpaM#zv zlT*NB<PRiV1m_}}4li*ebPk&R27+x(cYQBMzjd5z+lj-Vc%Gh~FSS^C>{dP|g>Z8$ z_DxJQ&NLK0P4~Qm<T>6g4C#_F`oRRHC=ekKIv<RHcT)_XSfnU-M$Qu_%-kHz)MfL2 zbtSQT>kzlR8K`c2>->e-@3s^0566T{iRL4W230}KMg#gx;Mm(3t44uGDW83j`;(6= zrdqt%SIeeAf)pef6k)hbQhD#U=fhf4o#vowZKOCGq{sXDh`XvS)C2@?)GV9X?@k|U z<0RypO+N=24km#MmD~r4aPTO1HDLkdTYVq?xLWs%`!9F186)e&;jb$%m3Mlg9zU$z zn-l)f3z99jn7%~OL^Z$n6H_Z6C=i8!uAa!guDT_1!Pi1TGdnMi3q}6wTbGy4rxnZ3 zY&pEUm2N=xS!em9Ni}s(x@YqZ<+o@^x*>tSCHtEx(pOE+TGrSLyu8s}bZu=<O|0Y0 z9*cat=}kXaVavJqygdlav;MM&Sa(@trD@uIBk~%ba2$T((~YnCc_t(Qseh-O_4x=j zEtZzc7S%Z8$sV5ot15Z$55?an_HZM)(pLd}f=0S*6v1jR?Ms<iP|z94e3o~YAq=xB zb%Inh4g-m!Ig;v@D-UUIRSrgn<ud)CH>b$(@M{K<m||W=n5$+^q6<nJ)O;_XctGYm z5@MW)xzQ1`ylj_mC)GtF)22QyP-ACH-9@OqNj2TsIyit;O^9qAmFE3eZ5*`vEe?{0 zuw`Sv6D7Q6J0m#w%$m!Dz2?k^{iJI9dCCO$)@PL5H&amd5k#hL5_~^GaIFCkk%|D~ zVsr^aB&5JLKT$X-O?72N?qxRk>gzIw$zqwWP>r08O`XV(fh>|;@-dVCnguOW`0Na8 zZ{6hk(H;%g7CR&9UcspXPx^0|#Hgr~NSGLCXe6PsN)vB}GrZ_{UevYvl>5K`gb58& zxZ~%&y+E$Dribt^j(nDow-BtX<%u6Hy)P%75kPJ+cS!hAn+MLvhmP)J)p0=@P)kP} z4M0h7ziK{f2tBqJ13#E#tqu>1HW;i95ss`eZEF}V^9zJ8&{ouhZg4b5H?LuJc2)Bl zrNSB%cvip*lOO~%g?lcwW|6{Jeh*|qLDKhoz3<3^IE45OMFKslmaf?>W^C*tqqi(b zo^=Z%CwfX+Qa$U&LB5*&AdD#C2JT*4+P@u0pYEL(V`m0LTxTE1@^YDG6Wk?tAs@LN zG=3V#%89-nP`_8`Un+Y+PsC=ipj&YI?)eWjlR*gF#l~MINPDugDNw?hUD04}IyN^2 z*S5#SgBP1L^XddVbTUr;AP`(YED;67k1^UUnkiqW%y|1u1zo)0u0w8CP;0rkAe_9$ z#(Dd;(8}!GtkLIPR@cO2-7<kFm|(f3_x9RfT6q{#XZ4xOBx_&m2~g?8oTrONSk4>) zhRLoFXOd^}YI;BKK1$pDimwlx#y09^I={ZN*n%@xZX7{<tf-_Fpl*5VM_v93?uXH< z;`iWSoTXT2nO80E?a|>MqRKDty-Aj(fF_$%uZvAcI4-d2<tE0${cLeVDOvxnhFE)T zm@KFyeb-29-Ru$2B-Z3bNv`*h_u(N*ie*P&D69<@zSWuQEVE33k&7^=&R6lw<+U~B z4pEg3XE`}@Nuew>H@clsdU7>e=B)t{(8<@bq+yZ$14ewdYIBVzH4O$WQnG#&*D|m_ z6r4335SFkm+Q`2)wa((z`*_%61U(B!8El^9kA;Hb*uOadWIeyJO~&L7psBgWT*XjE z+7a9XXtU(Xo}$uD1eGRJDuv!g!;vz5s1oPQ9puJTNu{kX&q+Dt85=qlE;t0xd3l@B z2x#1qMXWOhkl(BgK<AICYIfwzR$q!99v!indm2$jELP0`&=sP{NwyCv>mX(7_X(b| z7M!=RQc9AK;Gg_3$#x#<_Tbaw;@DL5yAZs5YSmQX;o;jYN98t;u)d6oe~I|s681Em ztIgu3^T{yHn!Khaa-lNAiq^%#J2^SM`B8n=a(taWXeMdz)(oA^@rD*MW0SDAaIe!? zV6M*gOrC_t7LF9DW4%r!NqHw+_i`tEs>LZayVxoiec|R9wE#N9{jQUpl$lxGoXeE# z$C_{+GWM9fQ+n^6s>78$ZlJ!of5+{!K3E`>%E!erxK#l~fL;N$l5BSXpx@4*_7l@4 zwD$tYERiWgME9zvw3M-Q89N;0<)v!AYA+}av=^B71qvIGgQQYFK+T4mmoBrCkvV&u z_q&O_F1$*SXujrmc&~&RoCZ>22(?T@hJ-m$dV`lMogReBdn1mmO78zdnSS~!h3{@S zS**#Nsf4VEPh<OCTU{OU$ZZw+#_U<u7G+`m;@Q?{$(A0u=|BpvgU5>3P4G+U)1+aU z3ez=d4g9v588ua3^~ytk;BmRO6i&pp&`z&X@gt?_xP}jnNGMMctN>?!4`mZsr&`Vc z9Wv|P9Pibk16i)J$9@oTz4~9vWP<pl#t2$#uxk03bd~j`U;dBNL<de&EL~MIwXr`D zeH)dK3qJ`FYD;LP698r@%J*t_%BzpZVxVIYtP&D0{ptn49ow+7m}Nx#P768t(DJ@K zd$FTTe|vt<oWt*g(%wwFZdp{N#u2)k70TJwrEPZ_QRmKAJ%d65!ekxe@rQnq#*ZIy zr5@vWTH>ODke?b-S0TLM?fclERo|EFmi1J=NWBHyvSCGfsJH`UjJZ&9H_qw$jOXOA zqOWi@>gn;_-ZY=tlSy$wCg%n9dzUtG>dBpg99YP^eOb~U{BZts$u;4V=BmphY;1v7 zukyB(MzhsX4>6}>4}xbu)(-$WIdf`Nwil>2hO?NdRIEG$`pb6=lg+q)Q~nsNxgq|j z1_BwPnKp4goO!*w-fE`N#V*lxg;ok7=UJaZVs@*gtK`B5Pomvy#h(8Dz~hZU{sela zMtQ)%Ltn18TD2H$7(rMNc4ao<S=4k|n5+GoKL}uMhjQ<o^9nE`>SVQKA^7Mtdz-Aw z0Ts*<TZ?{kdy|qh>uH_LRzyNcIoSMlZ(*_CnW*t%#49r+W9YdVpNj^^X5NVK>oiA1 z9e$OcNT($r+XPe)Z$vtU^(z5awP0@WfUjw%g|ZirYH}%mywjh=?q}w(UXSl%vY1n9 ze8<bn>-+iw9|-Wk<VH&!vcAtjk!ROCY+LY%g{~mrG^MQx#H5T6{GK0^qaqzFl6!v^ zDj^~1L$bafsY-N#p!I&b&JIyKrr1GPSlK>xFeIkwZo8r&-(%1tvLmS~8N0Uw*;FAx zm(hNcU!`GNqI2aErtxNw^4r4o{nyElu7s}a!PsG>BQKuf>*>|=NA7Ft3}xIg8dma7 zGfO?5N7*BT3CTA~VskevQV+=g0Mty=1!alGD7+IE{1KsPoq5>s@<vdu!)CQ{#0U}) zLL<%lddhu2V=*KoBnZ4Y$#3oXf<Udx6dAy**<MU1dK_En;{iwyx55h}VndGB$+g}s zTD@lLQl3s<Y!sPeC`Hrll`kkAhv@q61-fg*lpCKjF9o()uO@tcYT>G+P#R-My$m&W zmE2%_1c_E7#3ABe`)E@A{D2Q>-Zjj(qQ`C39%ql)=uBZAC~6NW6=^h#wcn;aH=R2l z;I{PjYPmb_8ZYqZ+I@a|b*iUa+}DH`p$il3c5s<Wy)!V_0*>Uh?B78x0FjXXxMYXC zy&XNvkaIFoBhYGXJ0BBhjd{#nQ29!5xRSrCt5JflE*xLV{lNW+jO%oFJg8xj&+^6~ zi2XjI&ulEQbqQ@D|M+;V0o`d6t&J&}(~Q@d0F80zi}HIXm;+yI1wB`OQugbpC`LF0 zwtcn8C@qBejqjRF7HRktWMsWt{VkG_A3o^St`v)!6KmdWC~GsU>5*le`zyWK$)Qkt zt0cLfmRhI~GhQ+1Fi1NN6;1NfL}z&jC|w-Ar_fYxxhwM}SO8-5j_J>}aYCBSnR8o& zUNYk{JA!N8?#-*u6^#>tEvu!{*ZFi!C;IU3cYVQ-dkG5nyg-1O-dI;n&D0}xjG*x; zQz$f&hVy9AP_u_<{(eDaPyk-V^rKKeChH|M#fkM`G-f<3!eQ-5CTH<tkvg08J=5U) zgfbg>jaxS-7e8gnL+Z9~+7V{utB2NanABNh1^JCdu5^7Kt&PiSp4O>lYB1vq{P40x z&`Z0dK0o7nnmD=X{erjI6Ub5|CA?I0z;2-Q46BhW{5mA#!RCPLjV?b=*J#3oxIZa% zW;=wbx0ke5>OPGc75Bb}oBmn1&7`ZAPm*GYHXmmxUm8$I+cd(cw+a-A0-#UpewK4o z83yMhGV%R~isdQXcUVb4ivnZDPyyM1Y~!bT>tSLA-2;7nO2QFMQ4I$!V|Q6X2U%HU zg!o3Q878A%u+CnZd*vn_PNty>!V6#5(#!ftx90|KTHJ{J%FAsPPoDf_p(QS;vCERM zokPZXaRkJY(%_+OC<t2vn~tDJ^v91{+!}O}<B`=2p<6SYUbvkpee(3wqW|2fd)2YH zOace3(V=5=p`n?rBO~NqWwd`sCK49k^r^f1Su0Ks$z1iR(K80+jZkWl+w-G|$<vmj z4<+U12sjLBK?A7`ES6v-?};*fa*cZOMZXVk(E_kV2r#e<%v8>$&<T-})lKzYlWv;7 z-5rCFlRLR?vQyHYb#82lV1j(`M%3d*`DUxkRw|LIpkKGxfWsa$sbH76Eu*&1ICQ}h zDZXL)b+sxyT=|MN1q^-N@(p*lu<-Q8RyQbZY()f&G$6|ltLudcBe3!dl8GGH?u5Zi z*89779JZ?@2UvnO=)Uir1WdP~7nlr7fJ~$yg&*{ddi9Ch;W?_#G<r^j5&6L&Vi!yz zuRcBH*=o;<#u-E==jzxF`l)sV5sut|V9*)*($?DeN4J{9w0e9{_ialL*-{Z4+~GzM zyTsaOs?Zd<wUKP3+%5vni_yX6AW@=b*qL(sK+`zr<J^w#*aTx38?lcYm(SKVtT-t; z*l^{g2DF_c_sDL4g}ne3&}g-Z95@8q1fNmZlwdR}=^yX9L}hA>dyiAp7bdYgrsPbP zm#xJ%-PR@`WdyxBoW%~*jxIix8y@ucaGQdmmmJ1b-;gl`m72b*ct=Y^69D80mzPC! zs-gOlNNP^@=Wz}Lo<HCav)l7d4X1BrCmM_f9f9^ONqhQ!=^ZLv-cXNNWFqAh9TX!? zj3cz+d9D(!m-y~)RUC-EM5fDW=EOmr?eRg_J|AyzJlpOaOzZ+hCE4;<i4HS8SNiQx zYD5CYH|^nTM3u2q$Gw@Ig00PAOy~^>DPGd493w~=7x^T7#*8;4Vfx8(NaDGb8N>R$ z>&PUI2=t<cj1nfs<8sczo~@!t{<VG<%VkSB%|<27<q6?hP=I5<a+R*zh80Q3{e+XP zb&+_;`c1WO{yihK&Wdju<-%@(??hMSS8?&%$;76ijmneWj4oF1+%)G`n2_F43;POu zPIvRArkxuFw45A?d_(!v?bvXfDYaq(R!7BUewWA*%UOAGKP<Vqw}0)T@>FUuAQ_`i zeL&gq!1j)aI$c9_$5)lVsr|!~o^O6I$N>Ygk_Y+{C<cUb@(hB@K25guU$@C7S+(LB z!?`ju{Y$X0unrX^CNj<VngxZ_AzY!Iox2zFzSti?UlagMPyinZXvdJ-<BrSHJNu<U ztO<|0m@x}p3-)Na4uLVOb84zizaq!<>(R`R0t6yFpB<MlHYA81Pr87N3snz>Xixs5 z8eG|E!T$UgueGnTZFio{KxItIyWO{6hz*zo+6fg~+G>@x+;B$d-21cI^nT?9j79kG zYOMPeNZM@Su&}YeZsmv*&&3|b>E#GXN+N5==sFP5@w93$?Rx@IJ^C4*oHRRw;})j_ z%YCVaq-3uSeyS7>g;t4g;+gtDob?16+GW?Z6@y+v5C9PssZ9(%qT}IQf#4lH!ps@7 z%1bVrixLpHfk9ODb=brjECwH9pQ!Nr5n$V)aoDj5D+-SQg_!pqhe-v`#c*5id9T!1 zk!lvWv{_Zfp@r?uQ6u@zyhn5!Z<%UW)UCYQXGP+EMZtC-yy>*Sw~Gl030ofsEpz<m z@=yuIhlF9XV=hXU#HvTf*(_$;0Ykbj{2qXjiwn1%B5y~|brJi`aH@}mm>+y168{nu z_<eC!*_Be;SnI@ey2_6G%cahT?~8?ukJ9zdN(S+mQI`&irbDCJ$Q+{_x6lv~R<)-Y zx%pn4TyH057f3UEE!Ynb=q#qO4mBu;ZGWGaU9uZ&$($*-YO(M!EssUuimjF1LTkJ0 z5E;NQ&w}}JgOY&H9&)}fkYidzag2GO$IDN4_@b2ErP#cr+!hA7lwqJM{lC#>B%wCQ z?-_I28}n(r;yl>2ZnH6#IXvDWpR$|?ELFOJAgLNUU+%<;f6frli_hqILoS0)&eZ53 z+KLlDHiq?z(@O-AH8tMl`)73H4ooz(3KC<*$_R#xxCN1(CTmj3ihQ7*0+P*ayv=te zx)mJlTet(SLkh&FrVA}aNo|bpmWbvX@IOe-1iTzyM?P@&GcA9G_QTDt<poRtl})^j zGL2(3SV%0c%NH)+^YULo!$4QG+TNzloNTNccBIX7t8xkK6|=5xtd(7-N+N@BVflMq zQaw~iVGOAGiDqlG_|QYc!hG9=V$;J!MMNN*OF!mn`rB<prwV6oUp#RPc=D{)<WVpX z=>WK^y1-6RA-0fuP}4utDP)3(V)M<ZSBrLEleq?yQtS6P0-c`7LQ>LiQAJ6f2xuxb zo-}<aOkx@1bK{HdrzqD}30#3Kcomk)bQHyP`R^QmhB+PqJINE4gXO&FjJ=KY;2hU| z-ayr7d(a{|YrQ$(+s3&9EvxK=eAac~512U(*rw-fd?hBWTq$&)6meG#3LCzST4G;G zNC8=IsbdCfg0jpG5hgNme?5vPTn;eqx&o;2qq)-fL><cs+9>Tnl_y8)?tKZ+ZMc8{ z1l-qC(gFu>FfKMEtlI3n?nC<)wjGYo&V1Fa-uE``W<L~_A2eR$?M~GVHqY!WdY$yt z#Ipd9GFGe{DZJdT$JZuXYOi>V=~o)55y^g91Q}Ehk(&@@k8duQ(?j)&>Zj1mZ=DMU zln2t7o}RO$MGK1p556s5*vF_Rq@+MmMo8pF$IwVyw)oQA2pqS!tEmrwtoPJX=iU@f zpoVJ!&3f#<KUA>+dFr;oN$E0o7NT#65~?m#DcmuAoo+I;-8~S3NaH9_#*ea6V``D` z?iOIRarHoGYP)&wgh1NW(e~R&H`n2)y0?KA)zmdNbzb+ny+s5SakSb6QW?$d?Rw6e z-;C(Kcw;^N;nb}>i1vk1#w))h)4jQIA!m&k*}6}kdPD5(bL?gv_oj1NlI4qUt1l}m zo<opbCJ&D{V>5$PiU5!WUV*Kc4LbSf18>7VMt@~p*OT3ysKV+NZO{oZW1c4+kpEcH z`>GmWyayPb@m7cDvO5Y<E-tH@%YDr5m*Y-L)49ZsBL0T@Zl_^B47}G2l=tnO_O&j< zw^2!sVilKj0@ex<a(&{K9ob>Rm-b6VtNH^|mN~<y?gUrzHa}fs-rC%*xt2c>8PV zEOb2%(!vDQ6NHC$EbkjCKjKCZ@*yeH&~Um;s+7_($14?89W4*p7P-)-`MjfGVfpCU z5vj~!KFPr)Y#&HJ@5=E>?fNjnn?b#&uMuf$_X@%l!C2PRY$p+dAF*fh%}g<Z3A^8p zgy(gtw4@oRG?#ds6AV;iFBRM!e#zCj4B0u@yB=~g0T;Ckvao}AZdZjyLb`WlWo>R- zte!W>v;R^`$N*R`0|Ld&y>&@T4HqOHg6IMP^d`e|JeccRM&+n^Z#iCoj8jDDRiG*^ z0legj6`#N=8HbC3j|5<_GbaoJL8z$5hD)EZ+}tUY*GL@P?cl}(0s|4cnqNt@z+JRs zOxGc92()`xAKtfjaD$r7p~<$4o-_CWMvly7p>EGa&Iu)qe`WS31uiAad!9#g(ILlB zAL@|;5I4@b8D3Gs6F1-EFPY8xLr2+ff0C-G?_vQ=qIk7n1_=+hdykq9QDQHBswOej z9~)wXeehFOIG;^?sH}uyyiHA73u*Omh+HQ+_2~@>MIdG1!wE^mX&)~T&nqqnT<=eY zI6FEz)-S&HOwnp<Yuh!-NZMwNQtbYaPf0;o$hT!RG_@&Y{faR*KK?n*L4gR}mHQZ3 zL2VL^3Efhvw<_idLqADa>Oc=&KF%PZ%Ipo&Ab{>qCFl52G+8!$jp>VZcFOy27L|Z7 zS?BJe06KF@TtWi#3O}cUqGkYB*ptCIlSU7B6@*t_aPaVc)q7ml_forGW?LBO<OgRn za;hh^Sb#o+{HiX{b2gJ?ho=cv+|Sw)b%E|4Mi2~x9h)}CVY02h6@mULy&&)4`^$Fi z9*|DkBCFi{2g?TNbpxPvJLIkTgD}>&i>o0(<9Ye{kHX6%eZT>}&|IZR!b0?#;sM9B zMFb+>mDRvtaO>zXH8T{;DTWNSgvmWmJUqX#e33#t(XDz#ti3z5UBZqkBb)&o^8$w& zJyQwDT^Al6*^lVORUU@AFJ|}MAOKouSF8D^Rm~;pMI@y_+0LDM$9)BL@x@{e3)ZUf zlF#|34EBOMv9j9joIc8B3&;BO=Fk*Rxo90i=enw)n@53*SsMHAQm<Gv#uDQ4XvJES z#pviK<I2r$2`*10vLpbYD=ewywa9+JG~8pryd`mQa}$C)em&G+fcWuxlxwm!Ysb8w ztx5#v_1pEn^_H?bWrXj#iwmi92g3uY>WR7}RW>*syjebZ)l#YQ*V{?>9TVRQFz<K5 zQFSI#xan$mP#+mTp*&6;C1Nzxs#Wt6k`Ny|ZXJ$ENKa>&^O&S_l@hc2fn)SWL<3-< zh<q>Y&8(*7JSK%%z(Ax(*6F#Tq9QHYsA_j@O7Zku|MdKIX{ij*B(Hs4W?yV6Sg)>5 z6-aeI6`HNIfKAMAHHVg72&eTC@LB2^d1IouofvvEU6EUhGvH%+B`d4BGYVzO%8)+y z#4&E|g2~~D-v+L&u%DG;v2x9QE5lIL^(zi1t_9oB-T@8-i}vKZ+p;-97KPeU84vyX zz->0P+nK__)(vfX6B$wBUvQXU^r3zA>Zwm-IrtEbF(uU!yjqa0^5;`ix&^(}+81#& zmr-es?<~6P_6i+bBG12uhJ*_AR)$mutRlV~{G#A!2qYX&s_*lasXKShZ<D8`i!QIf ze}7INOb!$MdBnHwOy3a5`;tvN;O^bMB;u(>Wvt5NTEib3*=pf>2K^C$-&hlD@!cL- zUR*EU(GK;djKgBEwMOZV_UEU-SJum^n1ksaE0eBifL}ThuGfO_#eTT+mcslERzP3h z;o8plvi?w@W5cW|3ZeMYg5x$8bm}xbReda%9AgXDI>ndk9_T*oSz3x`j8UCDc|ISW z=r`X4)F1}!s7qC#p-+&}AU5Gv(%|B?yy*q)J(VG;3xqxgl3Be?<{gbwr|$qO1j4Yi zHN!I^-q)9hBhEer@zG`;QnL*wjG^(;=$E*i1&@2X*2ze|8`Q2y0^PUSjuE?X5AB+Q zyf`i4Jx-O%4@1-fIht5oc(uJ-i03?K1uxcT-*i3WufTwK&{^Ku4{&L@$WZO+4<BgI zu&~+}^8_u_W}sUWidf7h9=p4Hv?U00o*x>wWy5}MxQwIKRHKlP&2uW{NY;wD`HZR6 zh#_OWhM-|bQky|$H`4`GIYuwxYk`u@cdPOgwmCY^;eCl(92ZjSTAqy<Hnag;zMcqe z7y$_ucWZAif%|mJTflm+<DPV8#~X#!o8j+6%6QYpZ(N0SsV(uju^fla)4MR8#fBw; zieJJCT?-mZ$r8wYX+opv#JgXm@P|4SEZ&^k8GuR$R-Q=ym8uKG0HV&B7vt|A%SV}* zfQ&z_Rhc=+wDF)Gu2EC4ko!wu2HRlI)m7?mZC{8hiNI)A$vf2QBIuppYGy7y)!qqj zM$6qbKkj^oHZqRAQ)4-c3<M5sC6c+`JO)~R5d*C?(sDFR544!9pKpaxIgn+iP+H&h zX>DTYBbQ)pC`(}c3?|BgyF{*S70mD_{rROLs_ADWpW3$}gz-c!fYhMcXd2~o;Pv*n z4+%ij)HDj?#AG)OU)Qx284&_>mtLQMGW1Zu$!rJSZ{;7^Q10P6TTRS0EPY9zNbC~Q z?=N8JhY*LRGaN|#=!-Rp;WL@{h#_f3E%d`UpmiTkb^F04;F8ma`hdtN!k)X#12LBZ z1Dl_$Ny;3v7(i4albBzrZv$URyZN*v?wzniQ$O`=Feu6Jjjl-384!E)a$U7TTQ~}I z%>v=WHD7!e&CAOh(|l9$d0IyQo6~|#1->3qLS{9@!CuXs$wktuzh(u%%<K>M-}U9Q z5&Gmt5Y`dK&hBu#-)!Dh#ge#bY;OX?QOMR%8JSg+P29}Or7zrfwMSnX#}&p%W!lSC zWXgzqR=!BL0S^Tty&D$V4hP$<-xF0^&KLFS^$`{F)BBg{kG*x(Hr9awvCP$2ENbsZ zzd7f&GmYGB9((uGlYWQ?XzadMR><2a*wb^yV)zmS&Gk9FkUbQ9@S2LYv7Nio;~H+k zm03|QiAPkz?h)g2S{5kAA!2L?_}KWkJesJFcp^HB%|g~YdtRT|;TpfsG$d_(A0qZD zd2ddGaCdgS7MLHNMym4kb-kD(p|2mL?l)h&g0JMdKa6`IHrBW1wacY}tS+Xj3lS<Z z;1xN`n606+><#j2RTdM2M?6#78w<HQ-$D4cr*=!Nk2_~~Zl!$(lrur!oe$$k^*FgR z-f!IlapVwTJ*=ChC7nmoKH52YJ}em!5U=yaIvwDFHtLk#CA>`y9cM)niki>9R=T=u zby6y*x7REd$w<ay2y}?{7aw>oubOapT=Cc+EMzwiOtTX=o>SARH!r9%vHV0MX+!~q z#I;L8*=}t!FUI2O)NO$lba)w+m8e$8qd7<wvp4K<jK)LAhg*~ft-;@flGsc&Mg>Sf zOKTE0lQ<V+CIcF`Lep>gnvIVKMY}KSXJ+v8it}x>(8L&DK+NIlF}4A{_Y_8}BoYP+ zdY+39d7Llg%#2Y{<rnls)4+vuZwzXi4|$x_x*+ow9+6(I(zAY!Li%A!Su;H(Ez4j- zdfU2}u+U^?VMEIx4oyL>(A`w1Jl5<dJ2dz98~Y7bez3%iq7la9S1;|i`)Ftw7=mgR znn!wfTwwyx*0&>b?-eS^qGE({?`MWtb5~{cH*8JB$A^j~>^}lL95Y-Y%HFZAq`y2? zDM4c2sedQvaK9cD2-A@=Ek7=kZ17W_5FavGh%a7WXUp*OyW!6?eVGCo!?j{sWiF`+ z1$DJ&OhJUi;W`WPX}*BqvX>!>Bw;+P7xkwR#!<e>uzzgb`DBaS;pH-$JTeiRW?a?P z1qaUHOKgf1v~p&tChlv%3C_k$;$X8sl=-$%OL+$}Fvv?DIgg3F+e`ew67qw$HR2z5 z`)n8t2c2g3je?+>h3B-Z@yr+r&R`O1SGw(>X+tXLR8Sh!6w)-HXLog_g&G!Yc6xGx zwIgmpjnQha8yAPQDlhyo9wRP}V(+bfJ~U^>ZVvJyH>0@oLjz*6xjX@h>tLT~IoQuq z?{>2)g+`7D#e-zLex8Uf7z=7BfY?%4m~%E3hJ7lm{?Jykf<>A^dVmasU2pPDBlooa zV1fJFigdHBS_BzbTy;o@wz;`EwtW!Yn>wQB>sJ|B{I{mBNhpt1R;WAEkD8mOCA74B zrWIGmtz^vk0EjhjqeX<$#3ru93gBp?+HN##G=KR9^q8}@SC#ClGQ~z<&XM*%C8%aK z$wK(KEIu$$D7HM9!iL<%yCmQj+i=G|;oKcH)umYAb*4+;-W;8f(C@-}ad}j89G=N_ z3LhK$sE{F+yg-WNgTCANn*zGS%`);TVN-gmwwtX|-T9h=f#VBIh5~A7aTU#Z)_nTY zJ+leRzz<Ix?)$xtroDF7MhSk-ZS}yUejC~f8k;bMA1S!RL7Mjs4r|iL@$X%xWy@Hk zD8LSVr;F=vGoxQ&WTE?fz9nFZMnap;&!R4$ELtoGdEDgBb9~Zq`0ctRpLc$8kyc(a zCkfneikqFoAvJN7HLI8)2L6daaec^6H5uiotb8wjo>x>T&l3St`^e`Jt#CSngmy5* zHKQ@<!nYb|#<1PToee7Wb_1cplV8nkZztnwm}6M279OX0ekV102^TTnd`j8IMuBWL zX(2l@U)r4dgp1#?OZMWpV_T%_3v`i6erl$Oq|QUDm!#zki)1B6041jQCYtfbwo8c~ z5K~P?>rq{t)9=xU7TPk)Sh}6TwX&1t7Z*{XE%EMzajEI)8=Ertxl#P>cO8u8oBRP; zNsjjbjL5HIgTA$VZ6}$HOXc{gaL_i88#ag?S4qSDMX{)#IHm_KFVCaq>#G;jR7!-h zw?OkDTZ6=Xeco$5_?wlwFZ}&|K*!QsdKFTofc;Vv!G|Sz1GT59Aa>U&mpUxrnQ)?- zQHi3WA_p}Xc<U5?2M27x+i}nUg)6*V3c$I~%4<>CKwWUdt_IpfeG1*Jb}(xWTwJVr z<>*xwp<ImhmUU-lA_+Q&fXN-Lrux3|2(^_Y>_V++8Bvn`{{DK?OmlK;*FaV?h?C|+ z&qY>H(KqOkmo^0?;J<DFMYt$fZ))5k(vS5y_{Ca9P*zsNX3t)$Z3_Z5(4kIgeSH#* zrwaL~K8=kU9#220a)5(Sh~?v6E;hfYL*4`2Nl35zpzj*H?29aj3vL^46dmff;;$9s zD9K-kham`-rxtnbyPSU5;VukKIWi9RIOZd6(~m4T-)--hZTCMS({<Bme2krk`Xf3} ziwl&q0$P;1D#h2=J)eH8_=(Tw&mB?{-1eKnqt8D>*@p$MS~RDmeN~r^o5AchRCdhU zlqO-7^vIgLJ)Z|~*@wK>vsO)T9f3zir<)_$%sj_q=}Yz_mc=bI$zC5_`h4*~V>fi0 zGaet4mhEE#sGxQfB33F^uTdRF)1UrCb=W<ej@=7X&C0g!eJoUdoUvV^LwsDGsXDh# zAXA;4Urxy7xE!agB|Gr242);gjUTQOJS<op3AZpQ8GP+>t2nVc%?Uzr`q#8X(A-Xr zaKaKNSnNEH)*^MzE@1Ua52^W0ze1GJhs>f-TKf9<<x&%gLjF$bLblEf4(jgNQ4x7} z?8c(pY!?#8qU0ak_p@)$krm@~ALj@oN~ft6Jog1HTvK+0qOX<=z9o3cJRhSR13Y;^ zr!1e6ZIJrH4I<55ZGH#K6%sIq{7ag(3brc=xq)&DSs}$ZvG$+y-8_itozcg)fvmJd z{Hm(?Ps_!Og}`FDQhsF05JRW;pL^ty1GY}`eWmUlp3Gb0*Pky&1)-<Ap4l|9m;epJ zn8Ddp>z@h=0^jMcCko;i#a-;g+}kU?j5+E}@ErLVLH%>0s)v|WReH(hHc+6G5%Huc z^toIidI=Z^DxH^i0x!X$W>oF)QI8fVnrWqujM9Ifkk1C7)}|=fEAUI2I~&^Wqt3z# zBTIWue145L;JA;f5=d!DPGPH&bvi|HH#rvPT3KG#86ypV)>4RmsrPeQgophF<bKSI znC4W)7pELPgOW<+f&^Y><k^)#YyR>+$~tN%Cf0t&GtcmVTUg}yYqL9NYE2q-6=_sV za#6TW^fsCg0A)d_goE3RdM<^;WxGn=2sA>MdR4kV)Yu3P4kOZ=hlVqbP*#|*ntD34 zt>R#i8^P#aYlbKOm`ot+uXXGTc>99tzt}y}q=1IT>dbOoDNrO>8u}(bRAqMlwA_o6 z*8H*Yh-yGcMg~yRI0?0#uVw)j?hKGom(QwJiQXXhX%otQxZwIEo{ou$bs<Sh4|-Fv z)3X`c`Wb2d>`Dh?mN|dYa^KQo{r<^VitcF$Lx!X?AFFUQ?GHuBNCk)&<CfpBI^B1u zp@a(xA1pW7Va-!Te<QZ4QOTp%0*Wmd0Izrh3VT^s4%~DV;a6$DquD=I?tt?d<-MU? z!At?G;|(|gKsaxjpf~a99&jZ)U;T76=^p_6^f%UVw8;7pK(huKJVB3C5+G1Yc(A#o zb1Ow4BzUnQ4s>=eBv34n$OybmrlGYTY?$7T9#fjhAZ0Hg^3aqBCw4xhx&YdJnQ#VB zy|J2Y4&rX(jdP!fy~-~d%a(W_6=nTOv20j2Ri}Fi;<q8I!}}1sS!8B<omHqzlNtLQ za<gl36BIT)%+zSs<b1?q^+K^gbP2yf_npKM`xs<F8F^T<<=HN1Z4G-4#<^4c9AOja z;Q~p>h3wzi;wH1Q2tIzB{^H=gfTqf_f3l#L+~<eItV91W(d03sMlwb`UPeK|SL+vZ z0uY(ujw(BB^|XA9&k~)8>cOp{!sB0ohrsIM3K3d;+rJ-|SQG3TrFo3o&t%QIZP4$> z4SIA8&em-V9|VfYXzn#Lv2;nQWLzES-xQDkF&ojtY=aey;ZH9w>trOhAXvSKOu)rw z^Yv#yZF?rXsoDH_XeAnE)ehBs`pnDIxbv+IK5K$Ow|%!13!cK$)H%!Q7%?M|e7o)v zo0E;(V$A^wQgCWt(PeSNy}4+I$KumeF2tVP!F+@aph<15E<f?_i<1%c!9UtiO%#uL zyq@-&vTcSp+H4bcK;GTs*4cEtXnUv(v!pc^>%5k)x51f^x}qF-FD)Qv$gdTEzr5dZ zp{>CK#QOXs5#!JbX5r|I<o(54L<srzI@A2TJSYPmyEDQ$SDSvj^+jYnyx8XzN6f^` zmYyrrxqMbvmu|UlqCh|SmeR+tX!dk%F(6T1dqms_yf+gdRAFd9If8IKq?^??IN0*` zB9*(wJDv&L6_$!bL_{RH9zNS#CPt{3CqzO+6JxP-;m23N3@OG0=>t4>(Owj~(Y7pX zNBZPLlRWh|s(T!5dY=O?6=>F2>Jh4Vmc$<>EFihHQUFh%B$J4d@H}q$%oejNN*Id? zhinFYdyQ)P{P6o43x^$7zF3nQ_6p@;E*u%8x0*k}*Pa29$fTLTxRaheIA<3Z!61}x zK!XhKvkF4yyGub?S$HgL93cTu(iD#OyA$Wr^ZPiyk6!;QacBjB>5vj*aw>6s`udRI zP!DvNii$EV1w4sLJ^;_TjP!xfhMq?`Ns($gbIWI&gE{M_D=!lyd#kvW6csxFWd2-l zm9lu@Pc$Gvz&>$r_lEu}gV#AY(DcmHkT!y;T1{6+5xgE(<bYIgNdZlFU`=}*W^KG# z{#hTY2r!=vcCHzs5Scgs9M_~)ZC4>CLL&|yUQtiq-5o@uEl};`ypun|1jc<;k<(TC z>?p!S@`u9vAuaq+f0a6ETyB|`vh`_ei7J5<dvdgR25A`TC6KI|nBxTTV1TNzRCEb_ z0`%^IfsYDF;fX_{KhB-xhmG<x*`dRUT&_x8QLh$aXjupQ1#5rSi=<=*z)>Fo7lkbt zcQ0Men0iBm?1$d}+5D>Vp$uRTuVEEwn$x*mbtT%2Sx+`UpQ>@xacd^EW?@*|i_i1? z9_XDRDm=o$4aQ}Rk-MFS$gKIb{=Y`cd1(D8{{qE~DkdfdS-G%SO~NF`G}-nJsl+gq zOZaGlTkb6t?4`JiDxNm$I2F0|3z>D+fUG?3A7;%DuMC7f^x*EF=<h`{>u%RZkLV?6 zB&$AJTiePGp}xI3YPcun_I!nXxlau>e@i71*ud+d#{S0upB@SqCtS61#;PknLVZWH zmCR3$ixrpRZ7bYwoyu%H6{ksNUAf=Tl9hr0#g$i{mJ}3&kuF37{$}RC=&9lZx{qi@ zNQ#Nbc_QP0%`T{#Gty)F)xhwE&+Qz-NLdkhb;`h1;^_<0lZ9*?h_-sAPqn^<#UF}` z2^};AgdbrKDVE)9x^*Db`__g`dB>rQB%rw(Z}p5B%-pBJ`+%6=J1sU|uQ#7JpC7*; z>}zz|KIgH0Z|8ZQlC95HS5@TEH#yo^JJ<{x_I~c`X(BCj)70oZp;9s9ks@0BODNze z41RAA1h@{35h5y7H!ng22^AGSAZ=CV%-$(nwY|7upL2aDpqayJ!IvrKZqb50{IVXW zhPKr7G^DiHY%d<uB?0*Pk8$`1pk9Mk&G`#5Ic*eOhTtKDk=Gn1H8~BNEvn}|`z8@x zY?3XUaG9rvhK3SL+-!QmN4R~bw`?tQ<<U;?KUV_v{h1D!Br;15+CnWY1x?4U^#qcW z12<CXu^Z*((Opz}Uc9E$ynY|~q{eBBe)E2388n-4EmCCI3ts(=@6^B60`j?mO9XWf zswikmEU$YX<?$<X`RtT5xb`8f+>-JcE{kf<xhC&*c{J1vu6wO4^K6ALED*VA@br8x z`I{<nlse#y?_HlhsPV+|AS}6`*b7w~_7~VN?^YgLt~9ex5H##nPpU8kC0jOH_Dwcj zDEMIah<KSz7Q1W{Xp#O!*@wYobiq$S)aI?!RduK@PIRp2G`?jytw`$M`!wI4abs(A zFSs4BTh3t9#D`y}v9lqBk!Rl7d^aWG+#VEuIGw*1lz|UWSE1vX(ktSLPnxMb7)yDr zf`Mjh-;eJ3`Idu?q*Pvdcz7hX=oB)I&fAZkKG5b1biG@Bdq<C<7yZvO0!AAr2X>Vt zQUSiga7v3TED*{{o>%1e%PoDY99|)&Z6_g-$ZU1@NZs*-X^>#!_Fbu7od;f58=lAI zJ5eG8&7BDgs<-FA7zYYY;iEUacgW-FuU04JtC2(Fh002vqR)2)q@9$foT*#oX<TNS zVFRz~uX3B;HQIJ(iiTafx*vHlTp!mSj9(EjjqyoIAp`XeTmg5OKbR31Gand}ns7>d zQ_0KgKFiCRGt#s1sQx56^otwK<J-QC0F%+Qi}b^0X>LY)`#xOe!5IU)He>>xLEc9L z-?1b8Yp2sge-X}`pA~Ve#)+1rD2Y4I>Jn#jYl~>!xTva%?mj%#_fc2e7N^~Mxau(q z_x|Inn3bCk-`<Jx(!5R|<}|FoSYGqG-T@Z6O|Ub09<(OL5~6sob_=!1{_9k#p>q1w zYY$#oIH+13(=s~k-waJnC2l;G5}QTgyTQw>Dr(xS*C%gtj>N>$G!8Hd8@#&iXlaL) zJ^q{H<=}akJUJAV-onRfkq}AaoWokbkX;I)p+`Pasn;t`j?uioJ-V;e2#Y`bbiYF6 z`Q#U4<q<+)f~uG&ut!Io1^I6viy8_G^=3380`JxaTckDn_iE;O@R!rL^sx<b-A|xG z9Cjv@bPw#`{!N+I&tM{m#Hm*yRF4i-S}|dlg2~eGmSw#$H7B(^TvR64BIh?NY2nX_ z%Ny=r65}2GKA^gX10r5B-O`$`G||2D749iMA0Nr;In_Vg<<xDtMa8R#!d><pk4p%@ z)GBJKbv-Q@T3l2%o1f7B&58O5i6GpV&QKR@V^ebkyY+}BGEc49ls66AJ3B&QQO2g0 z@Bq8{15Z2~scLq{&X3MwP84a%GwqGb{2pWtP+c-8ZyaJZGV1C$`_f+2tgca)mP5P7 zkfBc|LFMlXjJf{$Yo9(qh73dsmu%rG$p_m9lUQ>fE9R4Z0W<aS1ztD&W@<EC?N+GP z3$}%P5}%2Q2}Zm1T?EszoOr>EmKMIt4zD*<A#yOkbxi?|ao!ctwvHs+$?0i8b2F@< zzK~ENx0UCJQ3JHnajO%B=u1bZlEQWRZGzvwibhNXJ>$#==gR5mSTpjR4Ed3!;RA0k z_@c4**eOP~7AVqmT%F#IkCMLlLzjpEXa451lHw&)pr}ZD`5V+oC0t_U;7GVyYIz-J z<7b~#>UfYS7B&CYVo-2c41mNtb92(X)ag%B>^X8KW$7Y=+USEH%^6pG)oa%9zWv6` z?dCM?7h`0c018Xos^D`90uqur94g<<knxUTUn1Vj?5y3)$c)9r(h|Q)ovAP`5q_~I z)C<aA97z)O4q%Kh9qeQ)AAsBZFBFxPf&O<%gh|Os$MZ|nmh;`+)+(tlO+FoHYj-w{ zvHm(42(Ub`NS*C3{D?U+I?m1j#-L8G657GxR9ERa-q6?>O8{L#c)<$st=YsUlp|a| zoWJP^0bWA~Sb)f=O2NDJ@K8qOy*V3BN&V`HH{K|>1(8a-4Z&-+BlQ}`aLpSD<AP_u zr!)b$;p1?0wIS5<z;QAgYFMhJnFZ>ok^R$1q}PRbescDeHM!iMcGPf0qUG^4{-EgV zB4C^Or^;>ta3^P{{ukIKCOyp%gnNWNPkjk{-h!V(u@Sf5-8B!*&l4^OhW?>_p}tc9 z_nY=gCMz}xWArY;P~0ceFC~)7W@cuan~6mD`1tHi3a5)J1)kF7?Te}I!kB;V^zspK zPahl&*CU{B?(85QnH?8qXR}sTRRyfC$M<U&cc;U`zzTU;Sz$mA6D(`N|2Z+WbSo79 zTKM}%%EA0dL6O?Y+DC7Fa#p+Ba&qDg^fIVe*w!~b`vBeROLaQ}hb6BjC>K|F;r<+< zKol6^G%Pz!0WeSztpHGYmbRv*K0AjL2Fn<`e_&UajP_z8kJ3<-dx^vu!K>!zTiE4h zNQa)uscY0Qa+(vetmOU9th2xvgcaiNem%tJevp2ockhV3h=?%C`Kp_h|JI3c3MBxA zw+Yo>6w3H;h@lDXuPDPwhmqtB(VMXSarB&MdA$MzEIz+D_vdxltpcpHt2N{|WB$dV zE)Ql-kn9l5ZytC!)TputruD&={`<21>%(^v;G|HqGLZi`c)&^_(FY_D50d6@Y5DQ1 zRRLg1A`t<CKePyNpYeAAqVya_iRX_+1LJl30aNmX`Lg{odw%@NCkz@;P)MJg|6_r$ zz?3ey&=$Wg$e+K$12jlCuFBDWED#l#@;f8K%->S^<HPd@=3y#b{!QeEVfcvvDOlCT zs{9Wc8qfl}*VpO%Tj&2Zrw`AAS=I5(81g^%^Dn{wCHOy>_FoSFSEc-`QhqD!sDE|% zznA8}m*(Fl7Rmp#QWDv$zBQBKO=kXw74#qG%!9=Q*kaQE#a{Zqe<_0k0RdW*QG)&F z3H%n%Uq9(q;RpQ}%kiHU*25;&(9l2+e&<h9?En73&u;*e4(i_}{$E1>_~u_K{x8Y^ z?DH=#{*ubSi3E;Zr2N$j;O{R<{*~_k54HBM0{Vwv@|$b^Vy=G`(0>r*&x`C|1@wOu z&~Iw}t91TVI{&1=zvA+*xcrj>|K2XY_2oY)^RIdP&pg3@BryIpY5$WTf3nZNChh;v zCaq7Pt-=SCzb2It0|RN}fckoq9_8DW#axRU4>b?XyplphX(>#v^si>l&g4juNCDrz zePfJvM@FVt6b%&hiYy8D>^u(=i9Qc%mx<=}zgYVl#qggRqCgmkz*L2O^n8e{wCaN$ zdcXj%Md-UCG5+#-;MH*Y%E9Src+c{!zF6UU(6Dzv)ZE05#AJ5350sFu^)q-}Tzn)U zKflPk#-sCh=nzoZqe>Y6yr=)3F|pAb<lRF+{a2j&D+yzL;^Gi4J^{NYD>>pNa=4|w z>WH)im<oScSx;+|H3bS92?fQ!&4*k?M~4LIb9zikEu_zHoXLN1Y`0SDSF!45@rN9w z4?NWJ=tVfPWM)|%6$>j{P)<(QaM3ws_xfH6!WaeQ%oy&Ma+CH)C{MW&%%@6uk<4-7 zc3>wW_Zb;=pThqyP2pn$gqFf2R*)YK=2-y0yKM^qfpD?)S^>A@o=Ie?5x!wzVF9w! zGhO@AJbF4L)51C(t%0Sw9!OX!#LFm<e<pYTF^P^j5H8biaE^P}lN{XGB)k85{Q7Xf z9gr(VO9wllCw^+JtWD;Z$KZ%|4>*g+#bRe+!I~&J@H#Q`2!{Bd1IzS+!5~wYlhagS zU@EBXXv$0VWOY%TtK_64A&nFV^h9x=+J=|v>eri-F|$lOkNqGgg6{6ZA;7+nX|$_O z|DEmgM1a+fa}->?1Sl;AH#R;Q5O0v#QdPz3^1a>#gQ7=VXB%pJJK8&LqI$TbUmYD1 z0(h)LP+MDjsx*^tnpNl6>Gt*CfysY<pjHRC@l9m<1ds>KF!nKVaLAHAsi~|Evz#aP zrMwF5iY?Ov-~-tD&@cdWE)oXDe1<7QkLzRRpMKQe3`fGR!wjr7S@+@{K!9;-#(G6p zGdE)kGsGh!AkQz2l_vq#>*A8q=?Fy5EUBS9p=f~N5LtR_=t=gc{`;GqeQx04K;4Up z#^}ITPbp*;hoWc=x{3y8g*?jhww~~3IQ!(}<g7jm%NfEme4*6c+8Q`CJDdENY>4LB z5)(Gxe-B;)Dd7iDQ^}~+F(bx97TM<s)b<X6pqtxw125YN7kA%jVei&4xCd!iNLv`1 zog{mvV;aa`^xyX!1qTN@WCCcw4-H?*QWJO<aklz)bsfR9DhDI)h0i<k#&W)C(u{^0 z8YC2?2_kQzf2N#&ZMHQQjsvVCKBXuQEa)w?$RN3N+P;<59-PBz+J3sqYXtBmdLkR0 z|AaG^==Z9v5K&m*AzO0bUkZk4Z<CnNga5ud87>HJQ0#!581UbTvHSpVXESjDPfbnj zsbWMQ07VOIeN`^WFD-q(Ie7>)b7N7X`Dgz8m(-I?f*nEKr-#OmfrF(Tk|D;q$qkyA z_>zuRyngop`;o><j5o&|8fNl1p=rkS1G&1^N0%%xK7T^8^j7VEov$Di6bS1BIWj;5 zaS|D2ZQ`67O2j*hJyJ{5eL#b@u7i)JBDZ?zNsef=Iy!_h8wzOvKnghoL~`y4^DoN% zTH;U6##L`c|0UcpkAg#8_6P|xn~KO(4{MhBOk|+Z@@yVpAVc%1P*5jl6Se;P|KmWM z0b%ZnIpPB52|+Wqv_xSxv=0mn?0RC`D`y5qMn=v`Pgswi7#f*-K686|dz<Oy;iXbz zX@UFraULtitt2S`31h$F#KXrIe<vaLKV;hwLKLKMy!k-E_lTb<uXCOH;4JozsP6j; z<plx|`%=02b{ltyGK;F{6s51OTsu-FEKz$C_@b%PKabN5VL*yTmpCI+3V?R%Cjx<b z!|nab1@u1z^0&CRK7!r_l?oGCVUX}I<%1>rC3U+_-e;B#%il?lAAOC1=HfOA@Hm_2 zV_{|GyDa+Pxmc<zRC~F;(=o$Z82Xh#-U9A3zc(%#8YJYOSfM{;OosbG{TY2ajeXEl zpDAyQUZ<z=tZB2ql`|-!@F}WUpx>>&)_U)F8PQo2m@RS8TZs~&+}sM(`KmNHIs~_o z{SS?uXZfH3Uo^Xldh@>n+i>4UoZ)5ayNb&BHr<9AeCja=Ui`v7TevoPb2~R@+l#C_ zO@=!Du|_HvGngCvNwb0Nq{K;qpNlj9zw)*W9<Xd`{gldRkk50t*Ahy%Mz0T$EcW)^ z<Vj+WKLy~txG0>fTbbEa7UK02i;FnLbyrrpIyySy+sY<u@JOhU{tsZV=H`X3W{r>j z2Qwu;Fq6U269{nC6B%s)HD*76L`PRtHS*@Rk6&kY&k?R+w_H?~qU7KJ)oIQ~U8UK5 z+V~E5$umgPaXxEva5b8uCg}R0p&_rjTcH6=Mn?7^4EE>t<Mh61|8>p`1VFeH+DNv+ z5a2DS<(RwF)CxhfLg9ORTRA>O9W{=nR-q2yY38)638)fU^|M#Cr|~U8wTE02*nGKe zdrjJjd|uyFtgMcz9Ly&D%}Sb{i!nP+tM~2pC*cIA_W)ZCTv$j;ssa6X)h&(*B#=zV za+&~u9u*_q>w`oht{iEG=Pl+?Y0rkn<{kt1(M=g`?fcK{PcMqh=IgEJ9hCh6vkG3$ z(!GIxI(yk05)}~;xks^{@*gt4Wm>PTB?O-CT(dW=a{G*dg?cvZ_makWMf2AT{yV>q z0g5>h->C|NMCPeab#=ADH~arb*IP$L8GdWSBcgyPUDDm9bfXB;-Hm{hbmxGAC<rL2 z)JTVP_s|GRcX!9oGcYjoJ$Tkx=RNQDd)JyZ{58Pr=f3y8_O-9Q_uEezI?dRL%0I2I zzqtKo(9nodfj2g-eslu%>~KXn_LdlVcA~JT)0>8z%G)FXX`G2}#&g0MQ%g5D`Vym7 z@yE>nOL_Qzoc*sFz!ANoCNE`_wIup?x!!IcOlZ8-$W}ITQnXxZd0+(z##fwNZ$q`Y zU67_kAaqeSWexM~43V@ys4Yg5i@&G2q5=)u4pw#jnOQ4X!WybyEj*<^B3Sv)P!dpp z1F><~&>rU=MgjpaeRnurOhS-tzN#79hJ_!DdS3yT-X%lRg&;cI=1WDAYm@?yYF!N* z-1c>Cm*O$+aT8;H9Z+5C#B6Gsia0td>m*Y7A2s&>cn!e0{&)oZp+tjKOl%vTkz`36 zshn{#w2=gtO!%A38z}OKWi@kyE7~cN#s|<C*EkhtA7XxuQdvvH0AQ-s<enY_E$RR3 zI}{NTfcS-u99iy+=1z5PRQ)!xw>MuYk&!E`^TFG}OybLB^w&-SW)AY@5GTKtFr@aT zQkvgrwsY4};6VoG{1XvVV*OInZ=7-6m}8I5&%GjnbICHRF!na-{}QnM_p@SUpa)qJ z`Bed@!aVFUHkRKyz|Nmb&two6&>2Q{;ei!6BYUC~deC{ZyeL=4ktq{bDxY~NGlKRc z19QrNzyM*=RS7_8`!Vuk=bnv0=#%?Y&wt5v{O9O<+yEf(KAxLbp|W@n6d;!nDG@<o z!Ho*<RNX@$g2b$T%E^4Xx4(ybv_})|imQ^cWa4(M&3vcb?{sNC)N|94>(4$|MqQ@x zi(3A=d_T&ZUL))3ssXsm!Q4Mu|5xPu?`!adPjh*xa;4^E`4SHZUik_?8}r2eW;D}# zd8ulUS?uTM6FQdqhsoiIF$#**lN`7$-@?NKVU5)*=XuIAwJwJ{V73eaJ5pU6v(x2? z7JuA<I+YhMV&V(;9;{XJj28@J1D@+H+EF}pmz15vZ^8pY%Kthtch=DK0d9mXn*qZ; z3=^VHCO5;G0wOhab%3@#-<hKbj%~wP(U*z*INN_j9AW+^S&GO74Nb#UGe7nEWl;Y3 z@Q^0QB7%gL+<F~s$CWIjt?1!^ov2EGbTIZUNZ&eiTDA(e2bl5PKcG+WAAx|Q8Gvj{ z!5HTdSv&w8?<<hs+W8DUQd3hCv;W3A(bS$TKmU=&XQ9#ZV`k>jF?_$AQ#4o~CxtK2 z@4O#K1h(E6Q<#M=Rxo&Zm-4W;zQR=IAo$SohCq3N)Y7<$s|RpJDn>0;|0}QfZyRVP zU|dd?^;=ClU|bP=icZ8Odq+z4cbQX=MT4msd*j8=+ESi_w!WnYBDOX*qNb1!J!rKj zvCdCvX_wCT!<T*MgUd(erlhUJaj<PT2z)VT9Df0u&cx1MN@jQdKQ3tx&UY)GAvGX? zvNDX!&82dmb1RbtY#HzT2+t{*#g=ql{-8}7wEko|B5Z@>y2bQEfAXHllACk!mZUS( zD_C8xp&Q7Ay3H)#SkByB;mXMc%SENf|EK2)09_I{%+TR`_b_aUKW!%rXGrkX)YPzg zt8<yOax!WbwhuKQ&~6Q-S=gVtEw}nc07ELEE9aZaGeGFvi$9#S8%j6ROp1w#$;!%N zC^4?h{&`MB_}iHN2!jCj^u$Sy$WlO3GSNF};Qx}h{?`?g)x(~-_mlIZ78~}4iRJZ| zr#U7P!{0}Lz&<*fso{G03_YHAuD9-ZDAl^SIwV0(p5C^A18drk1+>a~Zng6+&2l^3 z{FXmgUa~OrD}_;D6Ws43<6YnsWb5l~_>T`$*77c^t2<aX`)6CAn_{OE{2F=w&q<wP zA2d#nYwLOGR9%3V%F|p_r+Zs3=R{y;V{MeA--Szg|EkBveD3Rew;-Rdz~GhkAFnL& zU8Dm2p2x(_C06vI!LPO(erkqrb#m57F>=JvVXo-HYYv~9s(bGQ_3S^)Dle~JIoC<z zr+rYd5sT((xNfLuT32r-NjHCqu}S`&?CoHxR6v}A>pna9!jbv^e=~t6I0U5D8$qFh zak4Bp-SR&oaO?2~2YHev-Z_`Lht)(cElMq}wjqzoC~A=~DBGkK$l(J6=fjtBztk-i z?6&RcWm8u&iseQa{v)cDRFVa?C&=C?hsp+osYUbG*{Zv;^-bU&v>}&@DBXc*l&=hl z>~@%MLDKH3o{qeBE;I}KAz<hHSlWp&2-tdw@qb9}|L5PgOaPpz8c`cD{a0fkfP2mJ z7w9K2XaJ*f{!&R9w2TPzm<71*92pzfpDyI?A00h%XA6B<ZdAP$-srhao@y$Np~K4` zaHD$KXjb8-1@vU3o?hDj$LE2Wul&=hm{Xtc9!3(^$kY@q0FCusuxirVb1<5Z>g+nm z<mBX5hgj;#)1_T;V5U`~+;ai*0Iajn9M2w%BK`A7nTs&21$%<!8_08O2)9eF%WAWD z)5^__pHFQZAesi)HG$57x_KY18Ha+yE_DePav#+;SbC6i^I-PK=qTCTyhzC8bR1ZN znwA!?HTV`lw12v8Rp^v4c7e@?i|CadIE(KRu}h<ECD?jEG(WGfxU!Pr9rRY%s*fgq z_|=W+L4)(@)r|DJ>I?n2U|wL`ft*|yVx0M;ZESp;Dj*OU&y*aHFx>lL^(gQN*LTs| zq5*ldv7d=d$jMIr7<La1(f(qjZ`%!Kx}3F(b8ANhMgm|o90<@KXRF2OZlwkOrY`=t zkrq&eES)5>mY7VF>X({R0jr7=f-H#j`ydIhlkG@4bK0`Tt&eWVH3>-kFfMR|XH46r z96V#@P_t4+b$u2v0Fi&qYp?Ogh12v`0S<*;QwoEp|8k)E?V!52U}=DO9-9zX#bDih zq?s>|B*^k)&7|wT3hbACd1(SDbWxkyzrv;;9RVQYf^1~TNi7e*pdf{QnJM8LP+T-9 zY>yB~+#U^wOnqA|%)!HbP3!J9;~8hxRntKFo5Z4iIm8ZeONXN5ZQ9{m-LoNdv+0J+ zZBoZSz}<@2mV)oNb&un#x8XekR>*VPU6_>Yhhfp;ftznqN6TfHA>VBO7`QxZ6=7o| zK*xN7M0DXx@KgKjgjvB_edpg;_H8((iTZ-k*KW5LA`x8WP12?TvwHp0NyK)=UrC_i zuz9PvMPH8M+7#0OdB1rmDp1ScmNTw>8tS7jy0ue4t~Z-1<kU4D7vP}f|BE3ZP+REB z8;9$aOkK*?d3SI|HUNmQyMr6_nw}UJ{W|=f38iD!y2a75LfGB%@9n5>(={z*P{ihG z@ap<{HdFteyfmn8r3{_Vj8<0ZZIOmR%w*Obu%2Zhk6g9FrLey8EA_yfay6vWFZ~kD zBmE~yz|mOQGN)a5{v9dmWU`Odf{!LR6*^}6hM--(|2=HF4Rz~wwK=VCeC9d3gb?X} z_L`2?Jb0mUHG(fl-`>^fkF5l*gRX|FYr}D;%ty~*q#9zM#Q>X<1Jn77;4}K2ZV?)~ zOk}#9?!<D5JKN{85PvJgrEdt4OY33mvw&oD3hJiMvui2vP~S@qdRhznI4<MvGkRtF zSAE5rF4)2kE}_8<w2n&j9tBF}?A#>9k4hD3D-;JEdTDS%YE$q0`TuxtAszy9CA;At z`;wcfC=y+}?fPY_Z5xvnGu)$v7!lJnN%@wRm2-b}QMN1BYX>BasT(n@%}J?YJCo%> zLCROz%m+<P(-B8yWs)LV^VkzDvJ0uV_t{!`TK1Colrb)Pm$RYqS;?%g9|fJwZ->*N zc3Nzxt}>O6l#S+S>o>p`?tD0~K$uCwA+nxFB}2!k->hE?!{TO5q-%KiHiqV1FU2PW zth0IPD&I}})c@0KVcmIBbTDEhQsyZy%Gwr_PD2<(AG?fPLZ2M3LvD)aK2~KTJv&eM z@GT^PaCDJnd>^!sz<N<x*!1^ENlzqK{EjdzCIa#>y{;kwOl7t^tZNTrKj2s$n=EF= zn8oeJz6FlS!g~mwalMaP!{r=Tm8;=XCm=QK>I725N5$@U_{5{1E<s?@Im?{j`>RIs zPZA#G#;uaT07VA4^Q0_BEj__~_2tv8>5n?<A-?i5{Zc<F0d}foeX$@s&85ltd5^B% zl3z*JEJTKf+ONG$Z?gQ2xaXm_$j5{wurUHU?<7KBT~y>Q$iK4)6L(jxKjnLS!<t}s z6_vEQp)>S&+rn+sCaPc1l>-Cx=6+o8tV|s3x33P?q~>4S8L(jFye%t{5AqhZvmGCS z+%y7$au*X`x@io+q;^j<iXnGLfF4L-j>Q1h0|#S}XVB`hq*23fkPow1iC+4O&KJaf zevP~^h@AZOYd?Kz=tp%IaLJ9?Uo^m%nmf&Wd3i-!!!bEuSlZk3ml#$uimknLQ(^g% zBCMa%o?nnBjX>2$`tcU;yN6M^GzhhvNfm_mM8g7ZdMK}UD>hm#t7VWU6@PdorWE7G zeLef*o4b_gZsOcFlcw{AO|8V%F#f#O@OMR|)VGzbv@br|e^b0wW>n1^gh&+V<O5&K z>t0o<n-+sY!@|PcRv7rO<0Q3dn#*htGxe@c7OwZpP-gb;-lcnyCeeacG6hdw1Mc-r zj-%SQ=|Jt;fc?Afswh(61eBx)VHT^>t9K6paP5a_(NL-WuXhbz1&U!c8tA?VGzCaA zW;z5(NAz|$Q%7@J!S^0wzo-A@uG@=U7Dk{ba(f%B^mVvc*|DmQsL(Jh7``ZQa~x># z_|7vr(XHL?qw?@SvZx&4_%8Wt7`DC9+fk}pf*l<_IeC29@C4o7Zs}o>{&ef_kBgb< z1+i+nK<EA3!Hf)nfw?2DvIgN6WGfvme5t;s<RZDc>hiMgxVAi<&>ZpJE~R>IwCQ8~ zV$4x1ER6a0$&%Z)89bbn%OEl{b3@=;5N$ww^=xwj1c|(sQ*lz+QJi}^-?Zzrv@mP6 zol%D`ao8d^<1#O=<6+tZ3qfxmm%}9eYX)um{#0}(Gt=K<EhDx4ww`GWS0u;CyUy?v zxHMhWxeW@5gtPQRpSX8C=XESGuNE!|J`Xf7fZMOll>HEp==!^{95(brKmj_e+Qz3! zrV3vML)=EfkRO5Jxpqrih8=9uR}sgX<sk*!-fFr^MZn3GisLpR#1q}2>s(n`c{Ldz zb3d%N_oK}T8qV<WUgBDDHwXmJU3<MGRpi&KCbpO$tb|a%%O~>g?k}g(CPATP*j;*@ zoV+I?Q~5sf)wlrB3^0T^{`1`8Bi`Gl{W4`%bg`#ZMYZQ!(c_<8xOENtWfGmO@C75c z0300MRN2QEpE^K5f}qTIoQ2=U6m)#wl`ps>E}4Sd1AUqTjfm!LW4_rePl;?!5SXZL zTN{0VJg9yxdiv=@mq4ueJFm(r5)IYZ$)j4Q>4<gnGd_kRJWU=0(}mmKX|#Zm<{)q3 zo5iNG<1}18+FMmqA0X6WfUi&x7gUSbYT<^b``>4gktr=ZjaJv^2eJCmkT|eEGO`nr zfPTn%<>=)6Wcy}^s~@ZrnOH;h473vmZsHC?V?nXW(I;b74{LgdJDgA_wyO|xWK@L? z5x@4{{+S)xKy+Wgg2%hEXn@NWBwK>mW2RW|>1&hLqhjWbX}?0>wz~OM5vvrHDc?B< z&dI{amCPDj6?iTW((hkuzcLp+=x0r)GLxnjhML-7Ke2ipvb^xc_>2;c<oeDw^Y%xw zx{TGiTBlC$Y4c}A*Qc3R?f3CjGA&c}GzHcZL{rR9`<R_QLYtyxlO8?pwZ50khwna( z3*5T|a>T|i9pz$M;3<n#Ww;7o^Yfr9uH~m@Gr?;TI%tz1WkiEPD{~9aY+Vq15m&~e z@N04(+c)$H0&plOmppU6ppNR!dgxVSJY=2L*8?$C4<-uv%6;0qNP8OK3|$mnec~$0 zn~um|mkTs8QA&G?w%~b)(fu=0xe4gA1f0jopc`TpD=BxDE1pJLUE<brb>WPcd;bkM zD<)3j^9?d`>8X0qx|6a`O@|TWN*Qr8yUbpL!=h%e2MV2OfZQBFy8@Se9hK&bDtK^% zq{Tuuz0v2zJZ#EWE-aX!2DU~vsVnQl%yXM>=TMDJDUM*L%{x@$jf)K`JUW?_z_5PA zjL*%2i$06@Tug5iXZ=e4OWSh4v>vzlu+5+&xOunNDdDW+7xMAIZ1r};?ImAO)y02N z!`0y8s+AY<Uu6|A%og`w`WhH0<Z&g-Uf?EPe?~XM8fAj^zVLlK<7+5nJTbq?-VWD* zT#OPx9`g2(*5}Kt)}krPTK2BBNeq&oXWky<bmF%mdkBWT`FcnpKarzi(8my!%+QdX ztk=p~8;OaP_M`8Q!xEN~B^giy@jMUvc*2*@w-P$(;%T0phDafeUVnt7pVbohPJI7c z>vv+ddY?{Q%G7_;JAotrz~36We0;s$`C2^$mh0Qqa8cK@>OU+KaxR+S;lmsam=dKC zvWL5>qVzL`D=^IWW?v?9T>VzIpKHJq6dE`-({-4+k*T{2&#jc1HD>_~cnHL+!o|wz zGfGl>Cuc6i=VeNku|rN$(VOEOIj1lU;|qZ2`c>9aqRf&xQ!0li^&B8}z-!U#H&ZF^ z;zD|sQQ||*=B%1#81C*I5AQu;X~qCjTXxlzLMHqtP{b@aX+!e7p%A&0pgy>%gNktY zlCgJ%KK^?=I~-KPY{$)KQTd$u?5{zRw-d55Pzd$Q#JQH<G-y<#tEDjkKZN4xQ>DyP zv^&Cv=<(R}v`k1I>9x9(lL}(z^%D7##~Mz8IYAueFa1)S;b4?g{K{aY2ZzVywmQ|5 zpzo^dZO3`85duRuV>VI0)s`;nrjA>g6}P_U;L2q0_s7IF%Sxi<(IhTSyLD{Pq*<8J z15o!v=t(y`Vi`3IdG6HwUe0gHGY)V2=9ue;=EgHnyHwF}mX8MKf}@TyJXei~3aZf~ zwfmXp_+KkJ5cr?cYcgSYdwW|QEnKnu_*zQ%e6fTPh<Z)SKKp8`tC4htjA19uRc@=< z72D<-R5Be2OGObGgqahz(5VJli>lJ|)Y@N8rZ3<)?~LeOQm*$cf<>r3jzdh;4cnV7 zkl<yy#kS_qTvEu!p=)5U=xq%+%}Ztpj*5$<LvI))@D@xw2)Yy~h?QQHob_;R^ma!S zOhW}E5tf_MyO1e*UhN+F#^B2(Dd(wz+~IYfJt%6^w{sj4a;!6F{2TWf!A4g>I$;~K z6+#-{vNqOjc5g_0J@Ghy<5TFH@?ka!>-38s<z#76dTreIL2u+@#kV#Yj*eG2Tib!@ zCKSBLeQ*l%ihaq{CJ$gLhY~H$10i_sNyb7#Z~g4Kx)@9;ZSVZ9T#YGwhmw@&HSc2p z3?DlJXPI(kq=%B^)BHjoedx=w7`sJ-soA24b0-yt%#$zMKtFV6-G*7Mqiw?~%)qrs z6h>J1GVEK0M^99Rm8Bf%rCJKMs`|=IilpngD!f0D2(lGxmx4xRLsj#?M-3vYQlw>q z4!P`@`#ec~_-KFS7%-bapa-O`kK7ppipyIs7ldw(>SgeFcm@+3l}%Tqu9)n$PO0Ha z-rVwA6x~4jf(rCIOH)_;wqK;QUJ2q8zr0xOrE(44OS27Oc_`dn5F6cC21RX+hCF`q zgfyWw`}A+R7}L###&$%*vHoAZvIi+8_d#pl*pM{G3nP=0W{*Eeu4C8K*GEv5Lq&nK z_L+KAKQuk%E-v@SZRQg#05SR9%~9t0t2mxp{j$KZ<hd0ofB>1umNnz?F^1qwM77u0 zblRhCBFNBAw(S?5s$mU>;H+qLWhhqilEhoF$(yw?tVgi3gIUk`9Fn<TKjfCNzcBFg z{QV)p_xB)Os5j7@QL`BXB7Me`V0;r7JqZgKe%*N~L1SDUjXoJa+dl)-)h!+UJU%tZ zq-bgmjJlSk37H97MFp1O1j1@fw60W=b_ZR>rEge_YSRC%q3-}>h2?0->aqq(SB($V z_v~}uXnN4V4=a?u1};<-E+UVwqoZTpfPl+9L0?~rkeDfOJkJc7!-_V)kvTjcW|^Od z3X7!{Tm!QsFH(i}J43Lf`GPi`mU*I3w`{GY%o1)Sdj2>9-psg@V8kLYH8eXryB)?W z$u{1DZeed`OY&h}NT7v#X#^}}e}xopX6h<h<N@;@WHT`jKwk?+N60W(NbFU}q$GHB z6E$_Uk~k~&%L0MT6^m^vTWFXq_z{)x#FS23jG7vd!DpIPjE?2OBP7T)Zi#Ikh#0;E zK24!SW}RGas4sv^z>=$@ONuiwJsl~-9Q`?AHuGj5eeuC<&jC`(m^9|SsROxj^V?6e zF!2gwW19yi{58w)h=VJiLeENv0c?V3?0JhnZ5k-&x9RSRb9=iV&6_hPAS@yh;R!|! zy3J%^kt|L|^R)@K2#aZFEg0Ou*EGn{*@ceFCuIp;joW61x=W6~&*zBE3EPgZ(29#m z6x@~Y@l1dkF-{P7&3Za^1UjBaU+EyOMM5ZsG-6|vJa1RmRN`}Fmy%ecYu2%Y;PZBo z<j@_l^%jZCKkg}+atUDHC670&&EHfn@IXgO)^WBR7Ty}1d2crplePo3H`yIIfXh3; zWQi4eD*7uz_UQv*={)-r=$DP+f!cQc=sMnpV1QjWJ?%jwysW<@(osfP$T849;}`uN zL`U)X{{8zo7SC2J$A?dly@E<j%(rgwuA(7yv`TdsJPlk$M0m^>e1RKT@6X-|X6XMz zk_n-U-o*}r7kLz64Q9uO_2$~=Yv?9#v(=w+=9VX5Tm;?Kj?wB!mxb<m^0XZ*uu{+{ zclM>uqW~@!oS-Y)Z4Jj0w709DuivPOx$6lS<K$vrB;4BKa(ERnjdB|8lahot4r5Q7 zUo-=ySN<2ydBMmMo4&7a$~;4E{-m1U#J!b4^_NG@;m|*H%D8PDkFpvT940j|rBc6^ zZSv`{W<ss6)BUY6tJOqsutC`_*3bp$vtO%F@NIL{s=Ef~vSuS&(y+LOklwr$heqAp zOCU?u#sx^_iR=L;{s;`Uew`N2EfSxhD-vOyNz4IOesBjcSf&-u)zAjD0DBv@25j12 zuYR-XkTxoe!-c!w1N(_yiJ>xY(j(8jad&moZwfWq_Tu}YP1i9pA`>ECP|}A=`*48L z!b8%z*)#OS<~LqUQFSrl%NYK%XimE((MWYr&*{c;_^RVUrZk~nl&quxqUjfy?(N`S z&_G~B%W;n95H1XDd0k+L%h7B+eiu{7T4Uf?GF}0Q4*cQ4#J9$$G9)Rt7tk)i^Bd|) zfze2w9J{8zmDj*<sD_3>6d24$?cuhHE^qdK0_0kP)FIuKwzH#e`)KN(7?@|Ga8NV7 za(IEGTZ3i05b*g2zDTg&(zBu`m$R^0tJx~jqBGL?tnW0SCBHSKLbUXSHCu#l>$+Nm z?wMgK{>}XEYNX7-<#KHw=dUU{^Rqa<Cl;tRHk}L3qZUHnl~2=8A>v|sZnL@vK%$!H z=%<o8BUO}}PO4={3sWM!SMUvB2ibE%X+Q&?N;xr%9s%BZehr-5K2W9@CLdkL(XiOs z+G^DwFVQ)W^h*J%&t_uVTR;*R5OAk-`ZRiY^7%&D=q8RPE)4g6fB5zF#lD<{>+()x zr_)rKTHU?HnLf4PnB^31BcgzSz(<#Jj=wscad~xLVvw?GLV*3#ZmatJM$<f`QyzmX zU(J7()(V*h_qYOnFfMwO3_afbx}GoSByCrKRqV}i`yC~vyY%vTPeif`>gG>2IT{MT zg#h+i#mSMNBh`ioYLI-AP-#WXOh=-X>vZ_G=0cjCJ2%mRFFr*J8(HuL&f-QDuVu@a zYU{Q+4xSIXX6WcntBayG<v0I`kMBZ6C2o%3V0FF0ZPeMs@p%DVB2ePA64YcrTtiPz zFC5RTfmtY;*whZ$8`;!K(Yh1n&hXqKeqA=e8B~!GfWFpNoZ{GU6F`p4DlE0^)mUwT zkvZ>7&tq|y-1lz)Qk+E91HR}>mR@H}yc9eg|Gt^b_p!ah2~54il1RT+_NM;r<v}O9 zwaD>t#xLVA=*?9NF#YKu`x+jf(#CMcHX7|{7-1v6Ucwj27qn|4Uwdh=9n97(5K!H) zHon~qYxC5S?<??=IbZeC$R^X%dSY`u(}xyl*_Y~ZE{Aqq&WA^bz!Ux^y^-oMH8A%# zdp27vJZ!<&$S8UG`*h-V-WMXJz0G0pQKaRh)#_xeSzFI{X&CynZqD&Vv1Dz!ACOcs zEa8rso_JoK8syJsFsNM_<$7xjyc7!laip|6$SL$%Xeoiyo4e+&<g$*F2p_3GF<$is z=nx`%2bU++Z^=anO>`rk6aN0({##Ko^W8FmFtf&{D+L8MQ&&H(M$_ej6NIg`YSRKn z2qMVtkVcZU#k^ba-$*ub33y!BRwgaT68%_BEyh;H;IdKy5!OzE15{I)@A>0)oo@b7 z@Lm3%{kAY!mKDR|x|8i?C9WTEeD*tQrx(8~H9HoK01#OF(`#hQwi#Rg-sRsP0-b#t zx3Z#}Om_JLB3f&HvFBEiwES9C&z8aPKpD!A%d@k-pyB8qoSPeR@^BRDV%20B@oo=e zZSA-~`fBy~TU=(+U5JS?D`~w-p2scCemmB>>5L}3T(C~jy){cZc$d7rf5jKz+;DOo z-F3c8^FXMYVK!`cEjonqA20Fo$^8eLMU$^aIUiniLx&%=X774Jz(Eug6x@P;5(_*v zQcoHDUfy3w$ZXe|gzBzK6%}KtZetS^iUBmVkjRF(DGvs~=*XFv1lD@JmcjnQ#s8K2 zxbF~-CHxM%%Y75t?u0z_VduA1%*^#?pWT82RjkR>3Si`v<jpZqkKBrWw6|9G`DE)J zNUlpRr;nwZiC7rAHdXbE|7T+*$ApLtbnsxy8~H<4?7?0<{r3mBb;_}`hR*`d6~y-S z$-_!8*QQ4Mpj)=`q~Ol|C94xCdt;?Q@TrakHWnSC#;uzWD=xz_-C!9=Q5amt1K^AB zm;}bfKf@uHTC2e@f0ZWHxO~*_K56H>Pkt820C&i*=HjQ54WSksh}lB4qw3qPY8j-R z>Hhp)Gj2NX$c|dHgDrLe1N%&XxIakJS2X9N0L))|G91`}vwHex2;ZFw{<6&9b2}W- z4aYS<*N9*)pB3Cj9Z*?~W=9lVqX*WPOefTdi#R!~-oSH--XvGB-~HHXD0FOL+x%`a z4$zlhjR8GdQNIm6e=WudY}Nma%<u*>XQdgafZ?761{jx$tJ(7t_$be<4mWC8wXOj6 zT{>q)f5{gn^`M~iG912a&;aZpJLi|E%-o6EzIS<X86o5}EiGIJq-c0ji&9qn{=@P= z=P&{0kLvB;osv42U5zJ?xQ%P*gH8^{qxY_$w@9{5I<%h=P@kZ*SlM8NY@k<=%hDlP z980@9_V_Z0BXXS$Kgr#cw$qGJ+3-G#6P=<5Lsut!T|XcwWv!l&^?eA=S(N0Kb@n4y zjm92i{wdy!%wnv0+Ub?KKgP3>_3-Id0lhAKNz3KqNj}IoP7NLw)UXDa+q-=xa0yxI zHaQ6{r(lKW2H__KYPa>h-oN8@e_jJsOkFg^z7;7BpahPU{y|mm?nzka6^5_@18ki& zZm0Vww7FSg*3s>BUNqnT8qAEtZP;{<Qr_k^LZ<Mx@_qU8nA~)!ZXRanHaAGD07qTi z$=x&_KiW~t1X0rRwx9<8oC}0W;?&gpGH>S%YozMVB)s!?Y_21iVLtwhMvUas=>($} zVQA_$^aqRF0Va1VjQZPU8Xy*m*H?6><puQovH0qUyE9lNz1kNCKDd=n@*G#Ik7)Q1 z2CxCu(Bl}l9@6RjGIrW$C!fcok**=x11`|u{#Q!9LFf#apY@Dw3QaF?^Cy9surg+3 zYrG5&Wd?Nc_+wxyrjS~4sv@!u>>rHS7HJXJvw+@Z*AUdrbkV7*H*lniXv045`)Z`l zC_egEs{NYuuhzyBB(qrptmy?R+9aQFaWYxczbd^?fAr4y;1IUY_h;=$B{taB-ob%G zk%<>&;eM6(Ag?s(RU}=A&CJ{RL)<-=g^bnrXTx0V&d)wmQc=BhQgO0Zb$79ScJUh+ zksF49EuWJ9=^U}#OwUP8ityl4Ss9VL#D|KZv5Kf@J|HjW;6HNu;JHKGaxX9r51m)1 zp*QN^leuT|8;2zK|E#XbkfG6%?hKc%DVdP`fzcXwwx73nLFR^a@8tJdo|CYR%!)BB z1a(1PdU{~$%mH34$hiRp6Db%Jwz`H|1ZwS-{<hAFPFTDj8#2Z9=TxLSJmc#M2L>3m z-Ut9WpTL3r_11qt+;9Cej0$!*Iz0>|)oyEPvCD5#*`QZj^&#}8$7wQ>SDUFfQZAp- z<DPBF#jsIcN|#;nbse@yzg*R<>AguOK!zlhGqO=M-pH26npXArNJ&Sb{LP)I3*GO< z5l$npWZ_(LmikpaJ}On9Ek;caj2v84{~Pe~HH!ba>5^zQP@5)gLC{H!zw@`?KqWYD z1Jt^S8%WmE)6;{y|E417s;XaK;w>sHti#6OQ(52Aukvz@SXl?POleh_tXo5d5PD68 zFu&x(n~j}JV3uGcphJ8<Rl<ppK+Jx*i*Aq)mK^I#%8-@hLpBa;)QjpzO_3mfAYPqr zKzq>IUu0Kp0f8j1fBba`K>ws0`{lpZ=`{nHpN@&-4vA=ejLW?Kah%~A9FlFL;Sa7~ z^m(M>f?jsp80EtUhJF6lS%Sa3!1-6K7?OYy#EM-Xzn6d?x`yylpOqLyG^i-^SV$b! z1S9(6+ESzFk4B!4u7Qg&{v-m}Pj!T)uve-G^HbD+sfXmTa|3ODetKlXAZzJ?;f}P7 zMkfd)N(6>AtSnD212su=fu=mL<Z^3$dHDg5R2P`IwmNsv07K>Q@TD7SR?chV`BNW1 zAw|`AP@eTu_7-4^$cQtlvnH<1eCn@L3Be%70Wc*OphSG8^&Ce0JK|sY2v3y$c6J_+ zT>2ue_;`QI(+OtRU^K((JpI&9bsgrMHU}nGozO6(128-kBaH6mcma@0;pg&l9H9u& zPuMRm0KOZ~z|`MNtEbnq&9&hOfAyB_Rz>T|wpcQ3I{o-^0<w&5Jbv9@_IaGEyqd+) zJ&=g`7P*{B{N~spYZ@3(-x)1{jo_$3y#WppDVK=%)j~r4kojODYKsE|k_9QfdZBwK zeF2C8Kway5a3Q&kaS~Ve0GAAyNY|TQuY2aGXURW1B+lDbX4=U4g%`o5krT7Aa&QR< zZu3_d{CBeQ`u*XXi&;Ncdez)JvFNyiIvdjOfi&KJhID!FHz~+Oo>b3_k6WukzHGo3 zu)S0vv~TD`qh*&K`~##yCkb|<>#gh!kN%~$TDn{^-dibA18h1DnCj^6S$R_313wMj zS$8yI>KGu$H4@(~z-4Z-d?Re}7b%vIM<Q`)y;PG7{OLDlS1mRL32in8jW5d^RAzd} zZ@DKi{IYBfUN+%^&$<Zejrq=_!X`%>py1#vBaei#8E_6@4Ik{qg#0Os!+&N7yfcIA z--`we%snc~_#U);R#{mahVie@wTuMQ{p*;jrU!AjrS2y(ylq>%sbWt0_D(SN1|@vS zm0k2n1+8HK+Rs&L^J1#5jv$V+zl)TuLO57qy2QxIH&pU*l&~Zq&#L9=UJN$HJmn;a zGxoo5@5^^tV(Py-LZ3Cu6b!M+*<zCrlZ?&Jli$TSuAC2ga{~Ys%?>OWdhQL24V+YY zDR(O3P*nbe>S5=L$ToUz^PuV6DAaEb7|j#RhSO7Af!R_^?U;l{8;q03SLAfaYu(Mm zid*4Tw(TGuy-Y{Nn^M;x;e*<3m!hWAxIU=V0`$B?*Z(wrMv8-v>022MfN)!KS^r66 z5`gL+ztM{;oJ2$V%mSL>N9vVMCZA1yiekj!b{DJ%HU-iK4}kS{4%ISGfi1yj^SLu9 znak4-tVb3bA*Ol4AyLgt;hKmeY!g=<#3=42(HD){cXKqBlY5h-S6(WOB@;U4K+}rG z!e+tHU|Y+vBbVZeEnjd5psV0yKiv8}Bn1~qL+@>K68UwUL6Q#4wGldbX-%j<7PrFF z=;el@j7iijxjgkB;I{Z}a+!a}Q46X<7FwH|pSy$7L>%vuPjd6)u2IWSr}AqvzuWy- z6`v8V;FZoT@9V}E43TAzz`e6w$ZZKzSAp~iY}0v%Wa@Gizg3{+d<LvI`5r$Qk+3@U zr%W}8jqmef!s&COp4u*{B2kgXJB$!2`wTcQQCbO+Kq=wS`Oxa}pz&!^nIT35PPbB{ znq5gBTM=^FU?@2hAi2G*GE}vtZjR;p#o%%e3d(E40nyBAR^%fvBXi8Hu3_wBwhr$8 z6Hr=g$xK6r{pvkDozb`6`t`C4n|2{p^BTde5m9@zy94`+43Q+hm+;1I98h7)C~rwm zBu#*<6%HhEZ~OhrOy=i8P}JH2kN_f%yYRR<EwX-?U!RJ6w39~aWl4xBl#oo<&GSBj zAcu9j?!(PQC<)wdg~%i7p@$b%N9jQa+ImsaQ;tu`Z?^Cm4yO)Xga61xh_s#v>1kXR z8?>>vpmXc<_O_?d`&g@i%V_^%Nq^;o%*29G#bq)$Gd%YkLMiqSJ{bbIy=S2R_0Mh$ zfqdVOPcsBmOpDjBNmvQUUyJZumz%e;0^M3!6<@@ZC&%U}#dXq44|ma@v0xoobl*is zb2!8kz|gt)(m}4(sAj|NMQ%WMBNbpO3y!Lm=gI=l8H!=J-w(YyBM;B-J=ZWXQ0J?y z8N<Yr<_`w7-*JgN^}J;@Wsa_47+5stH5fY5ncTGfo&Xw>M!kpRtFBDVAF=OIgudyO za%Quh_nF%~b{lv-q?+d4c@DUK{`8PJXoQI?>W{r_dsU>%<ND<Q2hsg6I-MQ;b^)no zeyoCjb>8!Z?3%0=$RNFoS%a_t#)ap^N($;_Dk}%A+(Uju!zZh?g|6_)Er`^m4y%h! zH+bBip@kdSHtk3j6BZIq&m1O*fMBi*4SgM34E}Oafq^M*=anyB--6L}p2*rOz)Y3! zAQmAdeMkZAD@WWM?j)b~zhCIh*nF)poJ2=WjeWoW>h#0?`*E29Fr~$UpUEo`4cJX5 zN;^a(!aefbrVZ?RxNCTzG9FyX_%~RghGU(jWD(6r##NgyJui=To{{&1v84K^(RMKI zm7Jz3nUJ-kSYk$kPw^`?5!&`e+9q=@%{+%ww);)Zi=`+ouEhcUx+?G4rV%pV&uf_2 zIAo07i-_ejdwcBujoH5~B4^EzVe7X`67VHYD130?c&Kr^p`l4L6beO@p7MWBjxCG* zQz`Vq4gPiNA^xtww?CC$qHFi0WOB*tPA#S)@d#VxO7P#r*t@zSZDaUFaw?9oSHEg= zq?i9CcJEo}&I$%&ihB7d4}3@Q!ULuGz$(ybw~iaknculJ8|#^xQGbh1{r%G%h7QI_ zE}p&hlDxXQ{sjG&N;;{-bkmzgM?_~gER}(}81Cy|Ue-_(xIcx1gOmMW`fo~XW+(N% z7;qmMkGWEGN=f$n_s)tIqr_idEG?rVWyT7%nAo{=+H&R!=%C6!h=;R3VBu5QkX#pb zeB)`mUgMFEAtfUlB{f(oE{r9NsAPTWuAjIYF0@O*SE4j<M5XuvgdGaPW@iIofj0kY z-pBM}p+8I|%|Z{FwzLMbiw9IFS`e^iQ()rA#T<T!uIQ3Yz=kbOOt8~xf1d7rcrqtD z*jX6q!FX?J(PDYzcP2TTIsX+K3m)jg+k33_%_)P4*=_z7YjNo>79Z_+o$MTI)osv- zrztf~PFb0`_~zCY(Bp^dwCXP{z+N(;Us>Phdi($tFGp2SbF$ertU+<+4AXQ!w<n*R zn$q^3B>Z-?PG4JNxa?<jFQ!Dr%4(I7QJ$qXmHjZPB<#g+UCiECHQib+vR-o?wQ5G& zzR!W3<2qL`KXa76{H^Rv6Xr}q>BPNIA!QY+*T1IU)s%Ti8KaMoJ>6Impq87pgzm;R zXDw4RGlw9BD6a)DjEBwJ$jC_EY3l8G@g&u&rSm5>b{Z#2&qb}MFvv~)o@_>)<7s_6 z)n+?gK8*%nhiePG{S2-AOTJmgS1g$iAq!D7H$P=kJVCo}{cUY2-%|C)bBZs@|7BrY z$$Am3&=e}v|D4YB!94=dJ%X<qAUx2i(F-C>FE#@1&Lre_W*eX3j_Rco9P926KiV@3 z4zDwxsHVSsp-%Z=X?0Z7g6(mdkgkai)8i1KH7nU@vx|D4?bkiu_o*nmU1sr|d~NG5 zt-Fsr8}n*ZLtFwIoyChyjdowm;(@dt<?vJdFtW2_o1B<X=DbGu;ab;;jZqnXC`w5Y zdGPRIGzrxjK{@JPST{b)7t<NSm}yRFh2CBogW9aD*hjea(aWg4_3ba`tb&OdpjgqH zR2$~4k<C{a3>~M`ZR#cRx~45qI7g5V0S2ISE>_TP_@$^PrCWs;X4ZUJ>?q2ux_I+z zujF;!!_|_Y$w^;DyX+jM-7GAZ92GvXX%{d!JTh|3e|so7me!FL-0X^eVa!5(U%$*) z<4;O?&H$5MU-@cG8zur>UHumQ(L;nck*1bQQ1CmjKnyDAG!zt^RH@?x2|9PBe9o-k z1EW59H?+W2SUGx=##F)DpXnoq`$la{SjsS==0wi<&h~Ds7;Yf9{MlZ^C-U^7qPi65 z;Kz9hEViOD?jDXGZ7{2t?LIoaYuNK4qY$rgjS;KyQUf}qbPcp>MQ7}7ddE0V%ROFU zV$C0b$8^J^k7t#A9J!u2gS8{oz257vFf+6EQ$8Dh@#+;buvz|3yht=bLH|mZ9?-6k zi|yu_LQYE0&i*w%p2*?dn0-_X%_vN2KwT*ienfm#?K>juu4^zoL-ItzGa@`(`;%eH z`);lRJNJoB>%rgO*`LH^K!wRSw9^!sEOR?Yy^4RueJXqqd-(nB-4iju=-{LQIXVtr z`Hqz{^);igF|mGmB1(ItM(MPh)60vr;52#?=m5Oa<5iEf5m=Dhs^UW+S<E0I7ttPe z5v&z@w`19KQ{_K4+ME?Nz*J+?@5s>#EOK*_4`=lD9BnqULz(L9zt|pb{@8}Tl$xc` z){fs<=95tqS-J^55LX}xy6%s(zpk+c{~4H!>q1E=PduuHDj}BoTTR|EMGEydrB|{V zrSKVJ-Q58JLbnCBmba-7cJ{n5XGS`$&IYx$bp$wc!&!auJ0DgYA1m(eI4!*UUQ|~6 z)kC;C>m$v>FWNI*&=&`nu1-!OQOf$$OpMQsedx>>{|5T||9IzbM{c8^kzv;9$K%@P zYh#nxB?j_ZzHdfNDjS}(y~f6f;TQcIB&G6|KR#V-+iO5k<Iq2#9e$7~sJtPtx!&SA zEXfP?|08^jLPC0C-JF{zui)Iw%wI&igB0z<4Z-RYNWVz+%a1vfsu|KckD4vMLYxan z&w?t?emvDCr+7r2II1e^j0qA2*(<otJQS5FP0hYsZA)#_w6nyRguW7@G(3HUQwzmm ztILKJ(1DE=g1l0?!?nC7^-@Oi$RTnEK@K%UgtQ9K#&gNtogylUP+qg9)Ft#Wt}$Z$ zx!f(dsvuJ#7?M%_*`;}%@OoN?E~RuW;%sZ|NUG<2;S8N@)~EP>+AL6vr{QfIV-gCn zZO5`rET8n4`-@P2dqR$^P>Iqb%U$j$Atk$?_IQ}GAk4?=fFpVcp)cI_!$f4Y8GYe% zaXAvS-E+WerP4j5>Gh-#urKsFcgZO&O^Vgk*X;S`!GRW}dg81l{z~QvW4%Rz-}jAo z5ivs^DtR**L+V8Ar#QO$iCVffE&K`b0=-j%r&J<EHr6@`pUOs=PZ<NpN`4fKT#=_U z%`3e;`kK(kLP&QL`km$;aN*}&^<vctIH$;cOdk;wK9iJcy-w<hAjWZ<xz$n6kpE@C zLp;RW>%R5I?nUgY@r8w;>`nwGhCcHOtekgINr(7Ihf6)$EDi6`W6ephS@4JAfI=G@ zj0^9*Ehc`&#TyellHmHLYBzkTo8RMOqdXn{ox>8Yc!SdGB+8TtBf)c;<p-dE>)r9Z zoPsy|Q`=)$bU`mHf-XLEZIr;oq@|X@H~rIsoIawrtFg;}TrS%JUGf*3qj&$5lMR$v zV|I+IXQ*mOqe2<=mO{3P11@TPNhhB*@lP@541blp1$@!EjS5GJQeAFL8(?_Zb|1_Y zkfp@b4i08_Y`En(1=_#qxd5BPbCf5ZGhXGw%#0$>pjzjr(O1r;r4zi5x!>9Bk~DA4 z66~+7F$Q>kGdD9cd*$bh&jEo%`gy}eFPHv|r?rHSW-zh&MF&k}nwvu>1eRiYKGuJK zA(xv|@8j)Vt7~M$dMN8kmUVT(Ui#ia?*8_fr+SX?vH&3=VU<?00d+DDZihAI0I4X5 zTBUD=Q~rsYSBUj1KePm_L2Dx?DTPRu2Ol+z5ZnIyEjCUX_42^5yx{l~`?q-c#WK~} zfE}$k@R>i2y@T^NpZfYJd(Kj4o{6O;b(%GM7(t}pAxSxP>H7ETp-KaDu7y{E_kGmQ zR=Vb+gIdLiKJZ;#T`6%mCgx)7iqX0V2zWj(wSZP_J2XSLy<V7^C3S*E9DU7xhI$ed z>OW<bWFPTscFC~rEs;^K{dfZc%j|PS(%Jw$CYmC2-kda8He7F6I(STciRgg6b)7g; zh)+9e1*(u&c7Mg?smD23721eTaGn^Qbme}2+TDkX4pQB--5!!U52xtsq)RcbG&mE! z-55s`71e!=W;d?3#b2uh%P`4f%v9M%9*AF(P(KU84nFVTiqbW#^q^UUhu-X9M^V=2 z0MA>ZbGp*0M5)gb2s|hGFLmfa7{Du-DD=K8#L$fh^PG)<{uB>+T^x9v4Hdp$Pr>Lx zfV{rK=SD<hMz$|kJ7Fc!N*4zEdYe!=%)Z`Y@Y#5X!1@XX1_3-_23s+okv?Q(A`zZB zA*2diQ%_`FeXPmwvb5U0Da+j4TyaQgiP?u<BG5{XUE=F+9&9vU%0#(GkSiw#;Tv^4 zI$k~P9<M5(CE$J@b6joX(ivDFZbr5~q)RvrzGxAt*4g;$g{a7+$VBvVxpn#Bn(qQ- z1kImM#&M;D7q4Dl?}leQ$hLkMebb&}D^Ydzhz-LWS^VqTsTML+5|qkB;zkndb3ZS& z^7QLy3k}Xh;bY=5VYYIb$fz<~qQWxi<ZFd|g!{7v;yx{kwV1gPgd>>v@v|N2#1*v6 zg*w9sPcK-4nJq4BSBGt+rpQRpea!C^UX4aG5EH*11uvuQ>Qm!Uz-B=b8qt**uoE3! z#TSujGcZ1n+0D}!HSrVlOmcAu`~u7&WS#t}jv0ntN}j9Q5)vjrA-W<vR}Ia@g{Sfw zHb7>lX;dXe$%}KnsWu|#O+H@$jI3Uw)U>2;|M<=;%KpR$Fv8CLN9tjrOPDjqFgnYd z<IhrkGz9cuJBKv>^AhvgTs!aPHoGpMLuuvMs>n_7UhDt?1<A{fwMh-pC)CjjmPN_l zWhYY4gI<+*ogZW=z0zRk;>tU%lIvCw=2eSfOnpBi6z%Z^M3uHlCQPeOQ<TVs*Jy!# z?E5*#=a|<)tY?%4L>q#jr4)Pfoti}d8x9U$u7i%Y!^NE198DRw{qJTNRfHC_u1<k^ za_pCp$5{1IUL>Ak--LsJO~ET{5+}$gHOMcjlZmlNRdj8JGw(~pJVpw2dZ@9S;?Dv8 z6TH}QhK~j&zlKEffgmL(E3iU8A#PJBRQHsiBb4)G881!PIUzR1+#kv8&&Q`RKn+nI zFTlYHb0FrBaxNjMJz{>r1^F(36kPjoal4J{Ix;@o!kiaf<x&69HRMPPns<{9QF4j( z6E5Mq-nAY`6`d{yYdAfCm%8bGm0&%J)=3<c_H4`Q%Z<R9V&*yjqC@U9*6tZ5<Y1}r z6+mggi{g7|3)|KG`ujKpps)~Zzd#y+=Wx&2ih@m80V`qrY}0Ca>4VQtjDjk{TFX0k zv0lDH*y43i6Ok!|w4E|Bo=;|`dbTim+W^Ax^AZaqBXy*5lmj{}*rqh2P6{b-8i*&x zSFa0zG|~uDK8#J<O~%rmpXPQ*RH2RfwM$2X-S(hFUs*5O<v9u^E%^2vd#*0n70#ho z9;5a|H+bVyqEnmkM%p(2O|1Tgco{|D0x!u^T8^<k>U`dlcDe_cCGtP3s+9G{trhx; ziX)YK*);Q>W3(4)b;ZbtvW@Y(OknHf=<So_77KhZaC9bBhdBu=W8vfk!k*hGKF*N# zq#P6vZgL~|PLG1wFYeqsXh20ugz(YW+LC%5!eIGNsLld^Z3;sC*$xi`_;N0sph>MJ zAu}T#=l!qCqZUu6sp5$XI2CC{jK8_qK|J$Tb12y<HTkSclv+c-pEFG{9}-6jDM`rH z{Buu3vH%bm;{QXDvxx2I=NIMHndP%@q0%=wne00Ze>bnT0o_W6x6F@ydqmaA`D(^i z+J5>o(>fL}wN$8_z!{<Cy6M7dCqeh?UIb1b={of&5>Be4)Nfu~rVj_9{j6C7h{?!! zO-y{!Wwl<f{3g7@17&queS|U{)E+6a2r_>k%9NPrm!lLGjJiA|caWpxW>YI7U%mQO z%$fJW_e^50#W3|N#kYs;gKBLFso%g7X0LV()crfvLG1LFJQ(x72Sh{PN;eJ<^9rMD zYTTnX7~auhq%);4v2$GUY>wuwXYx-l|GJGO`$TiXev0j;i1I}ti-3dCu}tIhsNtpx zcjt>y!Ebf7iRzfJrPuQE1TYf5a?zJ|gRL(`KhsebM#-7;&H9G&W`LQ3FZ-RU`h52| z5_XE%=yI{>0+fAdOt6;%;c8wTS9Y9xjvd~<INK}c_`D>wmO+5Udm&6>lyB7H<&@GM zPcb{+Xj0v|8R`fSHHg}l^%-6l;R;RU+ocC4Y>yRMBr>};{&1X}<P;qoGZf&+{C-%I zn(DaA&MAH(Gh4RCfWQ4M7CSnZzfxjxTxV9!ORNPMe{y=7-GF$ti@3Pf;vf$^Sz;7t zrWR~!Y6@xH0Kr~9uw%I*AVgW*<{Ib^Xk@Ict#JlpQOEcm6n@*gXI%8wO*3=@)LvxB z8IkZ%qR|aIFg%KFx1NDF<jcEL9>!W_Gqad?{(;z4gkc%bmA^Ll*F)oWE=O-upR?$U zhU)0Vll05YNMa&f`)=Ns3Q9A{e;ae8JL1~I?5x7E$>s7Lo2@P|%tdRZV7#n*qfY-D zPf!L`qbeSNmy&@&+k)0tR!>IPD-T}>x5j<J&Pk8KbvT@R*JOiwGBLH~_bua^(s$UC zOTR1!Nf-1U1uKdS%&bG8=A3wQqyYRCBO+77Zucwt9Rdo^Oe67zcPF58U7;qqg|SZo z66A;bl={?Dr?Gz3cis=3;!72C=<b{g|HFHtAPQ^RpAjDjS2D`q3Zr~A`pP;F6Vu~I zZ%5a-BqVbSG=8S1dy{RZuQF0C#eUK}3p(cob~uteeX5quv^YIX#__-uU`@VyoloQ` zzrtqcos&bt$#t4P%Y{Tn_T!_6*JV6jwGlS6@wKoyz#EA0Zm4z?@j$eUEQ)X5WD{Wu ze=B8|QB+Ccu2ZsjyU(mvqI7h0ik?`kb!z7L_#4hxkY7Z|L8U3%PKoJpD$L;nIzB%q z@ULVW8_?S?%_5qs5eQ39SBs(n-P{IoFiHLJI1`>X3iP5Q7kLl-ev%Kr$<AWmNMS^i zl`~5>9G`uN<`Yk&_20qM^PDvK)1M%)E31TO=6B*<<9P9LDTM}gX5tD~&3O|!egQ?7 z9#l$Sb$_Ta5p4wse|;YsC+z%uR>DY>fwuGwLgjiJipt52DgvmD9|70cPVvvS@$cRq z7>5BIQ>Z>hnK6}YFyOWmaKb-^bIm0MdEoYnc1b)=I(Yt=gyE!*rQoTY{|Cp>5ls#1 zXO_3udY$(5$B4?1!$+KRI*Jz;b+fj_lti3kST>_q<fbplEj${%{$_gCeWLv;OPiVb zFweKjIIHtFcl`u*0oJ9Dg4XL$Uz3XUPYXn4^g<sNgq>OXmhYi>kA1U|$c|-FbSQyI z5q&e{K30Z6_r7dsZ>&nfSj}VR>0mQsnCN1(QdC@ATul0JRSZnWJ!Q+78L{GgQ|2!Q z?6FF+&gLg7ykdRN!oI)LO)(ED<BXXcYAzm1Zy|b}f;_Kw<q%qb9Q8%%n@@$OI9ciD z+3?cOvmqh%YtGVjEp7BS87aAFuzST<6Ic$ud6tzN)*sSoGu}G_1GVNXe|QQ%kCnMm z(xR!x{dMcynQHUpM<4L!Uy=J@idn_W?a7^^_$%Me!YDplNpzkXEmPwyi*YY3Yy(EV zBFp5N)vu#YS_EpbjVsco&=PhXO5nkNLG%%QEiEVbF(Pt&B#X)Z_gAZ^Em^+&biS5C zdyzw~S*PEM_v|3S_pT7v1C&QcixG*Cf}ui&U-#Jvl+~y-P8bKn)5pdZRF^}L5!71E z1II3VR$U4szqL+CxYNILlP+Zlo&A4&y=72c-PSIM1xs*ucTI424{ianA%WoTZo%Cl zxVyUr2`<6i-QAtti}&>XZr{G=oT^p3DE?5)J=c&&#;Cj4-XQbVY|g)})7`47@b)~$ z6Z7J#kCc~tu^l{6iN|WTtP33no6j=hZ0<hAHPzIJ{`F2>&K5<6`GGOt;F=t4ghj8D z@h&x0$E2qyqz45_nJ^5Z(p#c+E;jRTM{|pmo~EXvZHQ{C(B_N+%w>&t&L6*Ateeru zOo}aPnKg3>EV42N$jIgM5lw3#bJ|OLtYTS5)HqxivvbmkI8CjAtNbf;&*2s>wP79_ z%}+`y=`_Tlqjk*84r!@g9Ac1_TcHD&1+^ll7A?QrrROvYI_$F=Dx}E~5fRC@s4xvH zqgUwIBp*M{%+$yKVh1(+{wh)?V<&^B3gCJl_aq`UjK0KeheLmQtMAu8!=OTTCL0kL z)bm0D8{y&DUfF7L<Kx;ilm!oL&{hT6>_dx=^c{DN&a%|`zi`{-l_+irMV$l>w2n$1 zS$9072|iszAKYJtDVl5rI;!dRwW^mtMGHvdicd|kDF$N#>+3AOvl3a|(c<XpuGU0= z|JJl1Zh({h5_2f?IvVG*k14z`BGm5x;IFl^8T}RfZtU$QIqTEsO$<j+-(bP;>2GxV z^C2HDSn(GUj_Jt;CWGC30`8h#eB+ZfmF7p<g!k{?$92Inl*75A;s$q0WqNQ#56H}U zdi*{ZTGMrybWLLwg46{IzTTVnLL+?m5Z#r+P!WvSg7(X^uQ)UUy!?=)$K-#Z*Qlkm zretc0XQ;p(rjTwMBmI&qsIm+exTzwiXmX2)P>=I&HOh44;b7++)L`W1j{XNqx^zRJ zj}Qb#I!GG-O}1v+>d@Vq&Lt|7aZ{>OB={0{+zqPKt)@PZKtBNhY#*N!_)f@9r?QDS zKMWgt`&?8sjTJOG9UX>pEV4tM#<u0I7}Ns!Oqo-CXQrV+nE8D*5Qu_Ul0C!2)`#tQ zLr+CToI!&T8yS*>*!jbk8WXY$X6FnR^F$@IMbECDVuuZhD=LaZ2^>A@9P!VE1JZ_k zVReVN_$9|r8tS0(dbz^NF;mR=`1NsCs?C;RNlD3xyuqo1oUo{sQjf9Aw&56#>BO2E z`o-#6aZAUQLniIIa67w8NAs~`q~=!l@j6qs;5p*vfVsMQ{k@KQZ?>JoT*=Yi-h{5M z?LtxIDY!#!8s8{EjZ=uuJRm!A?!oNB<i4)wvZzPI+Nb2sM|EZrH>;}ek$4nYwW~V@ z%0i>hw;SM4g(nx#3B7E2H(Pgl5i0vo#H4ZDAxel5aB;@ydf#YCIM%@nUED)EEEdOM zaoDcD(^QqnuK}mh9d@pFeTn-ZDDqMi#8FJbO3fF+G57-m)=>lkCN0G$HPd@KS3w@a z4-PUN{yb7_6?9k>U|*P&NQ}xS9XLo#!zb~9gjnvzv0fi8#G}$(%5Ywwg1Q<yyFFXv z4z(FDqdMH5lPxye^I0x6Xz_-I-6^?C@d4d_Sk+F(3jO}$5ZOHxw4cd+a7;Wqrxq{w z=if<5N%4zWZEc{r*A@Z-UJHL4-sr}uq_ef3&uOP6F6uH_<>e9R=u%;85L{YJ?3~l8 z0TGuaPmhlizdml6Oy-#aS)6($s9UN>_Ktcj*DWz+5!TGaBxm2`iJRNwwxiNyr^L|> zd2rgY8ZwQD&t)V=hqsm2bVZx<HC4z%Fe<epuDqPdE(nDO6*sywhGHf@B}F_}G6Gkr zq0pzYGU}R3!D+N0qwr!C5<Wgbef;_WLqfX*S0Wby{=BfH#B6AIEvJaszaHa$B!90s zbg0^3&&ut(a?D&4f@xo2eQK;d-v>en?SfX_c8L(yyStBnL)uH&79@vN@w$?aiAM&u z-UPMY$)Zs+))(J#=uUB3t}5V+^2s?(<zj5*?GXcfMm$I=V*O|7-qg$8YFW|YNTZ;% zTw;ZWniR^$lwzg=-oao^>LxoPOZ#=Ag)7z1FLCkXp8^?YDGmPmWoYBt%1_#Rn7sd| z3ib7o6L+X_+>+vhq6&wEfhFza1M@t0uwkxR4g_LzHqg;o{90`vX(oYnb_@l9>+1=n zz9R6h7zzlq`5OcdxDpf4;7K{2Wo5#;-rZM#0_wcIKia~;lp7w_snSs!Rh1dhGYp$9 zOiI-JAp4QrSzMUT%-6x|eWqFd)u>qnOLJktY=3;CCzARPXZY`~(a#bRt-XFz`lfT- zeAvrQOE>Yc{2INq@tO;*jsCjcTSSML9aOaa@ZmDD*paxGUT`hR90);mNJknWnfm>k zUsQGEN91i9jxvmYo6&Uk<v5mhC@-V(t>ovWpHA~(V2QEGymLZ)aNUp!t+zBcFRZ3x zD{5#^um!0pN%^SSS*-m2oL6|IzTDZHq^roF(KVs;k()r{OZBn6K6L%$<?0hSxApWP zY|;#SCyDtrypNjdOZ<WB#S=;5_{{s)@vHce)it}Rnd?2FmHeWPR4Z4X*Sm+i(8B?& z3_(lsm$Rw4olrTuF#)i(+ir6b*35+5{U8l--Vyd!>elANLv7j5Da<;$#iX;8`8~%p zQ5=I_$CeYdF|(99;W(cEgui6?rc@cNeMBfp%JrkIBlbS;-7(m>n<EWGKTX&G3Gtzf z*!_JGOk!d(ySd72>}u7O1=%>(A$BeT183@>*429RLI;O2zrsSA2wWanJ4E<%lzqYS zBL)JqTI$cS$X351em%+Fs%%scsl>zQrw70U4OOU=vpTdL2c|1kY3Hd#ry2-QioaTs z%F#lL`-k}7Pq16uOIHssamHvIN?iYJ>zdd5`V{~!Jqu^npW|45pO@4<J=Q$nOorpl zx^~tZoxnaGG92-{)b*?k%*`J#n|EPuj)P?p`JgRV<4f~GO@H|L{VcA}m%xEznEHSp zs+}MV?0|o{TN&FgVPMgiMv=;Qx$6Muuwey$)tE-`KM~E!`bOY++i|wP88)gh-BDNw z*G6+1Vm}5>&v8T5P+TtuKZ6o3yeD!JSYJ!~t!h&mS1y9-jnn-7l{u#-f{EI$hnC1| zMr<BWuy6)7&JvO`3Rc`hL%hM)jNO6A1&V@?jXBgE_m^<3cwj6#GYX)o<Af>~<N6Zk z;A65*T}6%OVwZ&v<fbVMVHk+Qj&~5k?;%$M@UePb$8L~V$|Y!YW{KEcXsM{_*B)BD z*K}h_y$YGs>vi;`S|e2==5H$dBb{|nx|Wu7>=1*AuoRE?^~1W9q235MTF57+)6pBu zgLk8Rim!eIPW&67CE7&<o5O$*jKTq{{UvKb90j4vbUp5&f$?lHI<oKKBTjc$k>@!A ztwk<p#1bvH?|i%UG6kGDN77tFrCYQAa<8lq^Yt_8G{m+)IAu$7jL&;&%a(4ORWd#f zT?`>#8%-C958{a*L_3`>%LXBzYHE+DU6yzKDLs_VFLns5>7(x4SZcJ^Qn2V$*LDda zKT{K*$m~qEHyQ_Uy28!CDK_J&KYl@2b4OZa{EYDp7TV+ieW$LvqfdpIt}(B-cXQjp zqLR?Q1Qi{z#81O*CECBZcL*0-oij^Xihk%oy=xW<GcmcG%yu-_P*s&eFeq^Jp5B@H zj0VvH_dK&_J-I!Yyg~x!VQFcZI~}e?o-Q-uQ)377yRD6u<%tII{reaS=E3b9%WNKd zmLw)?B#~SRi1m;9@-=;*kCv!sDLq~B>p61EWF&W>+x~&$b>9j&-R+4=F;w_O06{Ih z$fSuzqEnZm7nk)h)z_?e&Wy|MmJAKT5~FqB!r%OT6RCYKA|fW{XByNmxkR+oC@XbG z3e~G{+|&d!c)xqf>^<6ggmOKk48`5s;~&ybxwN#@D>fid*J=Y-9n;VX12^dXrOVOG z{Mz-))Jg|i$Ly>c1HM=Ee8TeNWJmQMDej~mn(%@ca;N}pzh?9RUS8h30gP5>9F=tV zgGy&pGqVCkp(k11mL+6F#H=2F7(@i5oUC<HL<B@~1rjBYsvO6pvRDA$UGP}q*^~xa zNLG1U#7_xNCt>@BO$w)%sIiosd%=U_<1C~jO+JZhJeHWv-np@;6nt+-LfeKXn5~&4 zVNXwJko`&e^=m5&z1962<uN&F=LYs0!<v%_cttor1FvOz*LnMTRXp#Nqi_&_n-2iW z)?tbXWwNyLSx-pd#{1Ft$tr(R%<y`nU+;#+pCJW4&3lz_rVso??DCas3;b*1ViW9s zncI7j#q$+l@3G~#oC}6@8nNk}AmEXaG3nN!de%B`M*R=-s&!ok&*+T1QP@pTt#@&o zTwGlzH!}sZFEB=@d#k~zENjX?o-2#^MfY@l;ORX_FlY1Hi*WY{XDPS-2Gn!>N%>*f zWkT|n^rq3q*W7XyP^O_Er_j!CZsME_QWR{{v5Y7#LU+PUzS^}MSFM-*Y@NsBGaV{c zQ?~upU@<zU#qh+{kMehEaq+k^coe_t4?CB0u7d;Dh%)QurljiMERmH$2X{k1o1d)6 zR}-N5i@a)?WZTkN#K2W6&$N^JiV6jBV{Ur9s-18FC2olLgqK4IQ~(wu4+<xXB-Ia7 zaodj$=C0X-A+ngT9uqV(KQis^OUo!!>)0zIpPAv<K09NXB~_d``BlC-Z)=K)M|VbM zIaUo2%^@7rm3wqS-Xxf`X;$Jx$-rL<B4L0vA%GHM(H3FpxI|v@h_l;*CMby_EG`HT zVy=&<Q5YY7D<oq!f@7+#mM|3Cvj~Wg#em5gups*zYs|)nF>iiJ$IY|tvv$3*CT99C z)U5V>YHlwx#!T;T>~F4E+6x=k9`Z6vhZM(teGDLenOX^Dh{SU)xlYY)%E8buIiQh9 zpu#-PIz0w5)YQU)Os&ya;qSD}A7B9i7aR7sRA{;?F{drczh0lD=Ml>743zF2Yh~s- zI<3p}3N!#^{7W?w__)$%DzBo}3S(USM?PT*lV<(&i&M7<2?`yOtNJR?xjqM&!-d4i z!*k^SXJfyT#_)GoaBu-0+n$n(i~k4Ht+1-^@e%fsCeLS4f&|W*mAaCdo{zo`9ydFM zb;YEb$HMgr*U+4V{b3&GcJKL^&VOg^ORN{=q+j{LA)%p^?@sn6ePt$MGa7A3x#*DL z4m@w`zx#IgGH_?42nW+fJKsta$*jK%Phs~E5FjCK?ys^X<h|!AZ^yai%{7OLCjago z%r)itzFuabeCqU$(5}+WUWR>O#v!+*j#hH<A>qf@i$?@H!)pi^u%F`iEm5l)M{l#w z7@u<k5Dllfe0gdWbE5=Z^3TGc(*$g?)ItwgeSYN(6L6K-pKHXXf?`CGY5yv4%MNeU z*yXDeYGgP^GOVZzIm%)STwPO?BriMe-8fuG7&DZNO(4q34P(yOO1{C8DUNR+C^{y7 z9D~^L6L9~hK1f{mkX32lPZ(s0#H4qdI}o8c(XTF7_?4E&kY7I8E#<uPu7T2I-y9fY zsDC`u;{T5QS{P0#vilY%H2P)D8+>C+al9$<zBn)MOSRts1Zc43?;TZWJB*q6PS7Yy zR4^vl(T(#jePfFD!u!=j&RcKrismG6vROds+1raO)z#g*5jboPS&2Ybywy7&pTEds zmlvDJ^b(Wy(0X=oAmioritMcSP573I^{H&QxM|ymp6d1L@yY?v6Bd<($@atl<+eoh zyc=l^wFSHrlWVURDVuI~^l2ZB1&MgC&ErXU99s-mT~2u1wl{<vyn9Mvq3%{aG1{IY zTi{U$oxC4SuN<5cSAKzn-NWt}h-YRrK_yL*Y#PB~1Z0H!34BjXpq4&7+Z(>!=jU>V zZuz@A_qNLSn&4BFme;$ElcU&P`{U~#Q>FNLzB8}*+43ox&|k4$BlKY$gSc$K^~SyW zCdX7oy%5X!2=&H!7y_JdRya<ch|jb5zPDFZ<fM@A&u7BLCNC^U`VT_Omgh3^Bk@GK zzrC3(-1D{kb#}-1X+1HDDk^d!2xiCkz)wn_X1yK)g3+T{a$smb?5sH-C64udz^7MH z%S&Et?zx1w^qwIOoB_bRgNzOLAf#6hmJ5O2yF|96iV9|46?L(6qDZvUmEK+n+!r== z9{-D!+V9<FXz$3ElC49w3{XCNAlKw-+{(Owg{ebdUrQ~X8dFV|dVO`bCX0mi$w`AC zh!lK1UkhcpOiTCb%U5YK?@cgNTaTW`pw5&JLMdHR_joFQpBKIOspY4%5R9M)*sukF zZ6BM>9sr$9di>Py>gvIotfA7%wu0sF0o`RC;L|XAcZUqKXZMl<kGmIgjv2xh<e(_; zx8gbC;-X_!ip^Ld4rILCG|{7=C_5C!(jjr?ecl{PufPJF^J^o-EalUfuK;^z$`6#o zeT=v8zl~-S60G3#+tT2&519^C>9Y?KhO+X<0yYH(;-W|_eS<C2`(Wh~ZARu*dG|1< z(h~Dw+26G#>JrG3I)^5K?c@}>w1VG1^!9wHDQS6T{oT|Q4Ae=I5#-^#p&n4bbGdCD z&?5-(7`))hkHo%cy9GO8SruN|`TvgR6Z3_H+}=1K(_FT(qmb+iac59S(52es1F5MM zl~hn@nps&Dq~Py4#oBH^)X&ZT{>@M4-Yps$`av^aR8Edz1Z@IlIxtFerZ|KF)VTi1 z?J@*TJ>uJLnViY+Y<kHdeKF+<#*sHFSWzWuGVID$kMz>4QZKVKPp2?(gfLT7&-;P1 zxwW-)Q%Ofh3Qx;e#k0*3jIG<as}oAZ^SL_mto;se#q&%LYtB9p5uj(eBZe8#>c!6f z2Un~87q0g0_dW^O>%p|eX7%gB*1CggTtOP!x4f|Rb>X40hhz^=&mWDJYLdUPFJ5RG zZTw?;@(%2J9pk!F@(5%XkiN^uMhtDhL^M$I5Ptgr|Mr!z1N^v;q)*Z5R~Q#ABGE(o zOnWcZgqV*p&(F~Dn%Eo-mQ1KTzva|t>Yb>(TxKUGzMoj7)p(NV>B)XZ?c1IIVrQ>< zXQPVDjZCHY^>>hy#Tq#|`WIukctU}2+AW6NZ`Z$U*+sc8np)`JcUS!2PfsW6T9D#4 z#I(va`s<7CKr{IG@DSVB*sM}4j@aK)ZJ?@%AC`s@fpim}+DhEfjs4A5*1w@a<2`y4 z4AddK$4jpcyD56%fs&@+>$Z8zNu<=Yy3<eX7_{$o`-M?-yu2ziCS$425hG$!wIbT` z$n&R=%%FxqX7CA<M%b6}m8fJrK*4d)=KLyAYgEitQmqOfG-TBO-aN_H0K;@JM^WAJ z3J{A<ilGSQmsI3x$jZy-Wa4<`nYrM6ZSt8dn-P+Y&E<w*RWlk6-@*36j!yA{1^VFO zc0_B^?=-(+C<1RCo5$>R8nGtBr&vy}QrZ+#dLgq?F=q3u&}ZFyQ+^0E7?~^to5$ic ziAcRsB2`oXB{C0$qE8%<oWhsLhL|@nP*6~GAa1CpVtARqC`E{uTq@-vm(8{P-tzM0 z1Ey>F#PDYH<m($7BDs=O@O}=l^Cv&rK%@MH?sqj}of>9VPRv0NBqZO@_lRDrZM)X3 z+lXEXKN{Rs5Y@RmlhrpiGPIzO^0Pu(vsiD~?C@1(rBnU<`IC-=Np2;DwCiPWx2!PG zEl(HE1fQ?RxhzKo<Z|k}*yo74PIyY#2a<E$k10He0DENRBLtN`UB{tJ{4}3Fn{L}2 z(mB|ZU^wpD0cy|e*3;i2s%w>DPaEHD^|I2W*Q-00<+#3j?}X4`dDXxz4e#m+gP&Vl zR-P@srSlxAEPAg;cg65#+zU9bN#Cv5*OvIUU0*I;C-uJ;l$;7D5Dr56I7jXog2gvB zvZ0Zl?j0kI><`1kBE3%^0=u&_D@fHL3U{Q3_t&zsjF)a*tU2KzjQlwU-JB6;DUYf- z#D*n7aeq6Jd4IlPnM?=(mYG;LkyMP}?;jZ3nDks_SwLKtkU+xkf=fj?bXRs(j7;$U z>WWjzZ~n$~Ohp|eCiVTfaTqf%KcW!e{8Dd5MrkC-vECJaFgY-G4jPG{Xr@@D%iwln z>_znJ!0#t)J_H7SAi!mOU2L?jv`G=!C2L-;8*p`Xjp^vfOr$Q;NXq>KuwA51hsvsm z5_!RXaJR+9hjl<}V%Bq7Cs{}&1ZxF?Vl)0s#c6l0AXOg#Zg0K0l?t~1$Y-x*bK~K* zdGVxPIapq9=`g#XIZt`qk?)$qOBMEdcW{)Fj=;lm2lU}fDw+zmC#S7er1cMu?och4 z&W%%1LQF@lLq=!TZ4da5QzU0<D{Da9m-BwUsx3K6Z6+tk#{pj>P*L`j;P(Nf*Flb) zS7k{>nrtLMR&Eio(}vba$YM|(aJ0Wzp)oa`R$$oBaYWW&@D^gyGV|Do@<~2^lZ1oV z1!(TIR(NxCG@uWtka=7^G5Hs(@+QLF%@hmogoXLd-$u*+8I++)P-MKwEEy$({jdsG zI+@vxw->UKDbKl@J;DbrUASk_RX!H`_IQnliA7|PIVw>}Sm8BByn$L}0HEv*^YSPh zMD8K!8zK5Z;3DOVl8E<ak4!8=pBWNalvS}D*--%sFV6?U8;NOOXGT-}*E%h0Mi-BW zJROq&ExEmghU(10QPq~b7M_zL?@Pot2?#=t-Ki+O{DUcKv(p^_<I91Qn71~5&>8OU zPu2ChpyPEvJxG~<xxTV{JW+2nH4{4<I(xa(V}A-)<=|@7@Mi+258#cq8l>mjte!is zKEugpq!qgkyy1r*I&UMta&FbpU0(z(67q60K}ZGJ1g^nx3U>hN=r<y}q#aJ9d{r1n z*CYM#(T<)s1sWnMd1}cfg@9^@gypvgpsf0-wgUh%1$!9}aj}OE2hRj13zzkwhx6L= zWylaKX;svYaZ0bD9L3fESMs<!xu&I4Ci8L=arF;pQU+8z>t$?FwhZK`XlSN0(OaSM zwyfX1zNMuk%KZ6r*?oK?K0Z15*|nJ<Sg#xui3lxQFD=qpNqb9SGrN2>Fs7KHY`@ly zPUrj*O_t`Y{4y#omunaVfo#}ezvpCzk$n=OHV^R^77TRc-_M;JQ_X<E*w-)4dW+@W z#;1T8OpF^6W**D8u`!DES&`IBUDeF2L>wl>BJZm*bfr{!;G<iKwGHu>R#f&@ITFI> z0ohy@A#c@*(ZSbg28PlszSBoGCaszhAvD#@Oio9rm#s5zfZ?0r>2^ZNh-ksla}&4_ zQ>RFr2(i8HzB`M_tgJM;SzKH^XzqAPeZARC<s8(j)cPKPWW!#tWZjy0icN><@-nN< zP2S^*^HtvUL8p#0U&m8ONKd=^+8&?RA-aIG)*g{ED5<0bU;YHQ+V0yoh&G@;Vz(7- zp}r9WZ@RZ!?833vlNHub@Ist7RW?0~K0aMV4T;!%-JM+`DS(EP&38P%m%+0p_Slzs zjI!}!bNko|4RO_*LJ4N>PNB@in$7doS}>Ex|AHa?57=mr2IOV?5iZHnpFWjQB=6qA zl@^82%fh?3xv049Qf?9fBPq{%MsXq`W<%k9(!pj%y}XXh?c1Lws`w4ObagpT(E1)u zH(5lZqGa%;x&tG|F-w|S+uC(`!Y@XNbWG<e(mB1kN5C>sI0tCx5}`;aKyZ`XIO}Tn z>?OZ*6Nn&6B5w@?d){WN9?!-i^#uOB4Tb6K*fZ@qAB&-x#(WhR8`hPwBoBZI6@)=f zN+9=)5Tu<Lf`B<~df^3zhAhEF$9gxLoC&%;hj^m~X>po=_dAv6dX0Rw>33|w?N09Q zJBAwU96ksQ*PZ`$+qm~ywzQ^avFvrQ)3~3nxtjg>2%C%2q4zRB?>;Qwk(+AWqFt8s z_;S*>amgcItsJHzmXmM$TxEmsaxgZgJSeyosL+@vq<3|7ll^qs7El3x!D<mdXgO}= zn%eAbu+6YjgM-MxQPBBwz)+^83m$`0QG0KGo2|Jd+tK*{QjL|Tj+SudDr?+;b6`Yb zP^(OaW~yc<#lh~38~RO4I4b`p))4^Xwtav?LsM=!){mXQ5{H3YB}*X_6?YF=-Zqof z(IME`v&`y~6d-}In+Izj3#zk`@y=b`+~hVJXR@@;%#>;>9b~_fz{0}7s;H>c%m=W4 zuA>_(7Ixa}faheNo=O~fr_UAaXqSkB_X&Wx3srn<tf~}vWZ`bla?6(*lsrKv7tGwA zfa2`3`|<U>dv1C@Ywzx|iQa|6&!_QTeh1{-KuefS!Q}aKzO869`VTTFZ8LuXHU?zz zr(4?d{7l(XAO`~1RDlqb)FJ4Gvf|RM-hyI3I62d^kvLaAJke&^hQA%Oj|1XPV$Kwb zQc;b&Hq$UOK57tcx#pTvl`u@GI9bf8Hm^)pR1|oKJ_V_(5yy~2d)!ZGs_B?7ukj$~ z0;71YD0B5)np)sZ64$G9|Gp;|{fRd;p9k}J95+YD$SBU`=z4bp7I;GUyt#=Y7fq`s zx4$9&G5O2I?LM3DO%rt8p7(fliFG9Y!(T@t<<k<6B5w^egkle$^^4yquYJKGPqkXi zT+Kt$+7Fo?r8%HF$RYrEmNJ=@JE&R8{x5MYdl;2(@eTs2AK)z^oT1>qkao5L)3v)9 zrPpKY;qM<Gh=#G4$f1kqi1cxsL_|1eUi7Oze-18`ArCV0_{!+&GJsOtT)7QVu3M|S zy`@9vWba(8{LayVvh#pjLBKNc7#oL4Tbg6$k|YxD-8<FE`5*ZFzf@tr6vii!6fmV; z7R&nT3UDAGA>`ZA0jLq)%2i#(845AK@KS>nI?DJHN+~|$7hs;crc(z%j22whd|J3f zozC>Bgzxy<Tu`nK1^qKGp7|8f%fS7xi|>UeUoNf!`Ky3?r+ehO?Y&Jggs&QB6M==? z`Wry#e%d}^mTqTq51>r>nO?fgJ4(zfm37*BZ3MggD+c}4<A3p{_5m_rJa|LQEo}cb zIYI&$M@7TI)wn-f(1zb~%(XYg2ELO5Ik(*rzbEh$0$;*uGhdon&;K%3%`Iwd#E~D6 zEu2zF{fwh)gN=m$qpf2J07v&@gapN`+h3HeVG8c~?Y3DTH*2}d`b_33+O9XG^d@OC zJ;fTHE%y<G1S|<(ZbRRjuKsS`wtg4%7mH!x+&dMNMohQ@>9c1$bIC$SM%J(wZ|2ou ztoTtr!zp9e$zs6=2&oQN-6_-ZqE8I7l*1nYGsCW5>A$|&$G7gKoqr<54-NkPdmKL8 zHbM)vU3>*$Vbc73!x$C6*s!qo5i*3#qHRY{RpmBw#BMtYT)oIcZuY(osFp!d!TDun zGBr|HBXeL36!)34R|M?7+iDp)Og59~W5ERYnvWGO)@W}GD*s>W!`hN4_}mQ2N$hZd zz-g>%ZsVgDaFE`wk`Zr-K4bjT+B(Ju-dvTxdE%jQ7dTmIEnGWl`bGft`s&p+pL5oN zO$_K1Me<@wOG`^cs=772UL}t|Yf31(QaOcBamhy75h-=MBAhGSJFj{90(Kos#O&%~ znLHT!f|aiI8uL5d?=bx2?Qrtb<Kr&JsAo$(kqZEyiHMAhF121gN9rYTo8e4HLladH zY_r4%*YUJ!>@emT#q)zcy{HJ@?P;WA>OLGZbroY7PwIZt{U?&Gd#LRGK+NIR-Mcjs zk2PSySZrfdQhbB&oKj>#H{97O2^L?PWCXr~ZLXy3T}U}xmFqC_;|hnfG*7?fN+ZW( zSV&0Dn2;xkmFRoK?vq8W$lt4ipO*2d9m$B!*vgLbOf$jo==B_q{kpwRtH@l$#HW~l zJCMjkFv-1Ge)c>8D>mpF@9!_@;!|ROs0R&aKx;Ld34m;O%AGzwJ0ER)K!$iuXBl`& z=B^1N4w%cB4rlwE)ZP<A1ktjGWv;@7uu}=}t87OgXmb^7^7{{O?>cE#0-)}zLl^f9 zqUz*1=<cE*bn-AF_|*YVmriddbM^ZR{VKWhu74Tj<xTx6v*u~0D$?^&@0`igt*G4L zddetFU+Bt%f%t$IPXGm{$3=5HU$&@NcR)5<a!!u^c2U-s0?@K%K&zAVApGW*R9w&y z>LIk_SL#b2>!lVg{{7hoF}u}(j+pd9hyL4gU>xip;gXFOB=~bbv(@U7`VYkX;ppi7 z!A8^hW9vlVcl!O_&`!_h>4*|Htu4I8Wye)Hyr{5{Z3tD6C!>57g?v^W8p=PY+iqCx z+#eov4l3M<^8tB1zLq@5F_p$?Na%Im)5*4G+>unnB0L@Y^?Bd^dV)qzs~YEtlL&QP z(c5iXq2+KWtbF&`Yz@uqDBXFk{eDvCdU@@Y=~Z#DqWmL~sKe>d|C$A0#^(nOVGxRi zEM%_fS^kjm1Md8wa3r^@i=1eGsR6+lP-n|vnyV<{dv^4vOmpEF^P1Oj3?|PTl)W82 zX%KMq+e$yfRng%Q5HKG0%gx1|WUKJuMtIhzCTn|;XXEy$IjAD_bGkWhv&!5SHtgIs zi}#9)iva_mbSZf>$9Hrj5@wcX^1T+_`);n1#~7UuXTc~r1+3Q2@DoOdyqce!*34N$ zLw3z#aa7K`$$QZq!INZ##|(6UE_ZeSEg-xeAsC)6o9s^s$+sH&q3CQ1HS<Abp36&4 zC41G}Lrx`S0^gJr`s!S?qeRZoqH-KaE-tQ?n?&>dj8>~UGj5l*>v|);w7zxUpo~1R zpy*F~@dt7H&Bov#Gx3PCX>tNfyK1m^%V1of0F@mxlAlNfD9@FfpreBZ9USiZT2v`A zm)(V=g9J^m90=4WE4Rl8T;hOa9(#Px>(}9wc0NszXHa~Nq$-6|$*~18guq7w`Nss< zx5Oo>8|T%gdhw4zNZ1GHPa*Cg;jcwHS4Psw$#Wl@eyU26t)HBT9dw~}>iA1J+uP@> z7UVD7WMAl!cqiT_9CINO2hD87s~W5P$opM~yt89ir~jZ&P-BBOia;Um?}Lfv+cg&W zlCi8F$698!QWGNUKe3Y1+#Vr7LSz3YSr5Sm1|kxMw6Q6~@gomUx~S+(P`eeHDf8tO zr;7di4`X)CI&u|lx#{!_*N*Tti4`Vu5AfmgvROdAmHd{HyHS88alWhWV0*XQ2hBV+ z7-XSu3DDa_8*k>Q6_=L;O!BS@KDT15?|XXgFP?5E5qBYLxr7v*bgLC08@v@3FOv9Y zBm)gEb#;!eiRX8ln52@-qd?Pnb^dfzkwrt?sy7qQ|2VgIu%o%EtUd>ykhTDsMdMv2 zBVfvX=3XW<%6Es$^9H8>3IT57Uv{1G86%jVP=14RW9_i~sYtWiM6OTw;}j?>OiunL zD8}Vjy{h0l=NLVw%2^|&H7H*m`_Td)VOJC{IoZ%RK^V4n?J1SBGm0$c#>5te<Po~n zN^Aq6lcnYcGMcO%UwxRzVFP`#R-8!>d@>r|p@eu~z-+|8w^Ca^Ss}m{((@3`g!KlM z$&JLPl`{@%wP<MS$-R46nEu}FJ{2q2<P<KfK7(dvX$gsp%F6ExbSw@F&+qqh!bS@Q z;BOS9Z;5I59ABQV&JIq%UgRp9$5oBI1*dC37dk5Bj12O)SYWq2gt2pU<T!ERCcHo7 zAUJqaxm0$%#^9r=f1dbSkViQIpy#4jyXg{Mo7UL1*iP5?+f&y2>CQqNAQKm3dx&-S z;{zI!HzTyBLu)lf|H|E~x-wBNLN{dA8Q!0N-g15b(8V(*GJt&p%MCDqoLjvIx3~}@ z>~KvwlO1!CS2N}0ej%}^tf3J|)~BbdEQ2EO;}kqi0G0QSYP4e=ePKiBB;8(+oibi! zvTun|KsX=%s)J4_sHCKn5q0`*a=v<yotjQdBlkG(d<Q3UAT}WS1Re$!COQbda;eou zJ1o!EbbI%3_9^ywEX_{;DAA)kpd>*60uIN*%nY4Ru9V0l9ycQw9Uv~_$zeWcaw_Bc z)Y9_uPO^$IF)`&vEWC?PS0(+>x<LMJ%&B{ScR$qTI(PwKcj)5S=or}4#eZCW{2R>! z!d=67Ga@SrF%`Z=SxGJ_RsX%$X;qpqchZPHV@lO;-+aCYe$mh%JN1(X0LtVy%Qzr{ z{}gUzhGh$Y9!4BMXWtX3$CIC*pODB1Vv?F3|6~K9^yY+(zpzs?Et84lt;NOp=aTxp zUDA(=<CB3f+>IVZfvEkQYBL9|mpID!ulN1#NWB{~bE^dr1olYzak;eJWCMF3m*V4% z?Olt!9P%XrwXNvGTqznEzE>?x_r%dr12jmd<9SI7mqradJigGrs7%_{hsyTn=>jyw z9}K%aKM7k{DJjLd+djhJgoY{RWs6CfklU?y3ZljQMADVwsP`M1rRr=|Kp_$Qv7#`} z3qKzM5d`;E1LzwBh0LLK{6;P$6N8nBQRJ??7tW7K|6z7mq)o`dQNPK3tIf1ZBKVc; zgG;JO9P4Rg{Q~pls4(wViy>4@%*LiJt^$SBhx{0dAmuXd`<L}UA8XFSPKjMs3Gnd` z*8iw1>io_Oy*<rs^9a6s9tzaOG(d+(Lc)%Oq>GRJ6xh`zN+-^Z`3??F=71_s^Fol8 zwp0HHLWcVRm&oz**{kO|=-K16(^o8>$%~}HimC2!ZKE&mefb;XfZmxxnG|m@{9WGe z_@Q?n_?2+yD$F{>w=+Cpa3BRLxzmZAmn-HLhBQ$4zk6T78lNNd+VsW${CP-;mnZZS z<SQimUYWfiit$a!j+(ZcQp0cjKLZ0MvNG~GC`e+{YK>ayfK6brjxK3vc*x;|jh;8K zKrxf7b%ezGIq~o)dRT*#l>h<g_9pY_rh1WiTn{)NRl*_$`J64PADt^I+ievDe9h24 z=H=&Wc|sQ<{8PmI)3*Gp#Qoo&-?*V}S8`0a36%yG5YCaMals?@I87}f2y9<I+9Rv@ zW%J7rS(6w>@{Gtw(9~z&_!k!9P*FwXD%)P@_t&*Q7`3*vn2eo@0)CpXyj?)DN6XCo zXY-VzdFwk|fT{uy2wli6{%JveslgJx6?<u$bE5ET?L1L&-hD8SKeP|J{%k@-cxcXG zTtOHnL`DgpnYA^}C>4*IrcQ1Pl3E=Jq+SdQ9x}x3R#XNcVSGF3|N8+%^}yL9m6%M` z!FYIh$d|UV(R;0DU5Mh~BpuuL6;}=ZTDY&sW9MLCQ@ESE&H5uI5j@V0hOYsB&i?(> zKq{2Pt?71FQ%st4zm85!EK_WXN6v0)V*Rl<bHSF3Sx|(x$xckHjdgu@D%<Y~t8u2x zX0K|JN39H%{)4oS*lS@yL{gd@EM^1g__z|y=@=mpd+SL9<Roc2O{4BJ*5Q$9|M!9a zU*AHc2mk;?evHBmPyi$^8xUC-vZ?H<dUL|S+zDC%fnMqtq-hyPd8Bf^Otxs;ic-q; zVw<Fz#kAk2r>E?a$Cpu2B;~`WPZ`}Ofczt!uQ5#NV5z9Kwswyy>})~g+eJ=5Y<Oxa z0Tm_n#QucAz=-_Qr_o3xRq=agW)Mg!fB9rd0`q5NB=SL8zV{-QBmiqF?e=^xw*IOr z>9gm0IIT)Y%BrN*t2=p2tMa7@33f~O>)+>?bduCE)Q`P?KWFj1g`I!<{7Uw58um?= zLRk^Xf`dd}Io)};rG`RT;PTX)w5Dulhh9A~ySh`}C|K2qh`iDf^b;O}FfmQ~HF6eE zfXT{@<pl>zui$B@#Vh;H59+Cc%H@`hxvM;vj1Jae{lr9RIXJ}jiSwI1fz4F1gz1z- z%eZ{R+dD?8<pJlXmX_s|&c=XtEXasx!sioIb+zs0>L~gs<DqJSjT@o@p0cvn7p=W$ z&UcUsBam<qs-LmqVg9kI{mZcSe|~Dg99w^k%cu4i?tFyV#;+=?L~v6Q_32g=dhNM# z0DCrK5PUpV=lo%vn^%p8iN^uZ!yr04`o?)Vte_Lkkc%b|Zay46g=8f9C`EDCMZY_# zvc%ld;*!bJEK{BFn1ZQPTh0)@|3dY*hnij$dCtp7`~+!(zDNp1lpEKT)|vHbXyd;b z44&I(i@PHaYQLQo?+g#><+*hRUS8DjdpG<e&qX*P+Y4zFld1C~qd~<eBAkfUi}7M3 z@{f5_`?>GaK0!dfzJ@YFkeB#D#`_}vm;0E4&?GKSvt^rU6mHUq27iwHO;1lq3O7_W z(wBn!YwLO=d8K2SeE-_wqJsIHWkKR>1IFVHXt9~+2oML{`(NE>WeE4(GloV)B+Wn& z^x`l*Zop_MqHR#Pex;8HC!!iHT|@E|&F%1@6>#uD<lIpf^Yqk9I&m5mBK1*Gouo4w zM@@I+mURycHMvUkND=ge4e<9LGV`{cARa<ndyjd9iYw>=V;G)Et0LB9dbr;C#}klY z@pV0$=a^IssjDaSC<y+y_iguWX3EtVnPe7*uQZzA(g?)&ZAbjbDNYPLJP}~SAQB*F z)=v1NT&-?5wY#F`c0b_r5+7Eza5P&%jhqmflhFw%#NT`vHTd6l0WtuMFN-2?{PoWt zvYNv|Ea278W=ef;a<)pY+{@_Yz|5}ygE0a_0d;ltQBoj!_#|t9q{C@Mws|u;PQ=IA zS}~110hmB;D1FD$Wy&^Nt|MU>BsVCvOwz9Ligcof@wFPxH!u*kq_VPJYVKcz_rHmN zKui=ihO&Ve$D>VQqk+`a<QnP2u#a4}t>0DJN*d`128L8P68$hRc)zoIlGR7OL-v|q z1kp@TocAlDk5(2T&F=7XXn4HwHose)oPV8@`eJ~@Lulxyp|O#IMc#haSYWn@vYRBe z1pFS2PQvBor;T5>j3D3gM~7*zKok->rzhi(mDj}@9(9exsgxN8f4|8P<<FwsqT*>E zJShyh55IDEH7!aU#tsc3O5q~*{a-=wf9|8g8<C^n{T>1WV}1DoAPz*o`2Bi-w{i0+ zD|1NUH-+l$p=EQ@P@fA1RTCWali;Wt7{tMokVqXIB==aF(Ggm?uB50>Plqor+VNxv z9(`WO-rZ?1m8mE#4MTkIJbr7b0|dwJ*rJ2VYBbl+liae>xaAM44KTR{l6gk=4?WW# z61Qzn#G%>++u2Qr*b$MCgf4z|DFUIAPRN=93+v>xu^_4v<sq~lt=AQvP|yS3lqAi# z<)g|Q?fUN?IBMX&0fgNLc|qUxEY!=3daD7KhehGZMHpUQzT$@6InXiyVsz~v6wrb{ z5^Pc{3P{w7q^KfTET{+r3BC5VN`CEC%YF=_nCQ8jH?pq}c4%x2P~pLqEk;ccMB%af zPfmVv*c(y6l1q9PpP5mYl=?>df{q?X%fq8CUO(PIk=a~{)%vo-P27w?Q@9@eP0ZHk z(=3&eI!LCRNm|_iG-N{b@AB$DnYQfh3z;<zC;lu<D(a8r>}=2GTcD(j^0s_tdU?4_ zN>zp6LVwOdR<^}x>#LZUKsl&YmYYWHs34VsgWY;He|xurY1vhepPR+gm-Ug0gX7k5 z;b83H@lm<N1{Rm!rKo}t*zOK<N4VJ0AwK6slwX~-j+(;nivREgXM&H;hX=@rX(Vcu z7L}BgNSk#w_zKlf29^SW&G67OGvGr)<5b;=_y0Zty=5i9^bP26xRmRRd7&!wr3}@s zNv95w0%icAO-VL$42AAlSK#EJYJqtqVy9a|Jf^DEC~OdlfVC+y_ej_NM+3T#wq*nM z6-+y#V_v+xi>6Br<#q0JPMb>m4b1!%8{I*Zz}9h~E086O!NkOsUR~9lB$LQR?Yr2W z)i5iv&a1h!qi0|$gbtE5y*tf`v#VcH@dgrBXc&pS3^~ZBwKd2J<m}`$F`BL;K^b1Y znK1`$El$nRuo{r(&H<tv>1k9<ihHcnQ>9k%V0AB`DHit?b|4&y`yLCc-D{0pSSSMd z?=RllZDi#FbO68HU$fefVfgv^>G=6YgA&L6@!r-(sDeOkGwQ%vQ;gOEHV%Rco;#07 z8<=?-La4NC7Z*1bSv&j)%;#&yG<QKEmLNd)e`Dd)*#O{E69<Kvvc+^;!K(86Ag7a6 zF^0s->>C2R05-A0)e)3=Vz86KFV+B$muJ{`b@Hl46BNtUG-FL;II2gp1R_okm<XIe zZ!Rv&JNUvc>ra4>ElDFG@9~%v2OU304sej&!|+PDrCnZj_i19{zY**I;rT)dyjfu` zHWPU8_rYIJ|Bz3A3bjWyu`tU?+{FeO^WotzYK0Wp7{CHI+a-DIc%%^q+HllP{iNm@ znHHT9Bk}R$qvR&H%{LM(cmosrFs}n*SSTE9V#%bjj%a|PfJ3hzx)BRPo^n6){2b7F z`z8OS9e>CD2>?TG9c7a2^YepfS)6kV(vMqcbL=TzAtBjKC)q)>nLvQl?y$nTK(=ao zKMAofKRtg!B<K+>J`0ceZ$reteu?qc1BcL{lpKkXb_zw$qxx+U0{XhcBC+F=MkzdY z6L>>IdGghriu(9?%n(e-g#vjrR6=xeCw|3gDv+oiV-geSNA1dMTE_b2FiW<oV)9}V zy%S$!VbL#LuLsAH@_MVDu&Q&Ll#d1t@_mEfPk6{BBV0HPHi%yFwrU*^F2*K4b6S0s z0u<tn^oS&SB$qcA)n+6n%iJ*Z3`0e2-Gb(MwzR^)n)Ls0-~PXsO;l7=V$~9t%R$)m zo;otrGD2N_#%V4Nsjt{{i;k01x0X4L#Zy%T`D7tialm>6QOkssoIJG8Sf0{b$osv@ z<5%sLZ5m#?o|fh^IF!(AU=6Nr9xB3=lqo~~<m{}1b^8smq4Azpevr}y0k8dRvWDrB zN-k0aQhaKgu0JD7Eu~Sgd9Gxys;pTc{KZ*;R%TAlidyv8s1PV+DR#;yC<yKyY?q7z zGJ{k!02Su!8ZAl4+rk*(LjT9xh8qEN*5RBK<NdoZ<XselAY5)G!c1WucY>KY4qUS= zUtbY+*GqOp)JknRRaFXL;z>%Rn)cjzx%k+xUw<YejTP#@57(GXh?bt9-`(BiN)fmB zp9g|hfAjJ39xUwXWeK$2-L~f)uoWsLJN9YSEDeke7u@?#Y!~KIz!$m>j4Vh4Lm>uc zyBB|Ef8Ss?-Nd|{`JM(?wd$Ns=u0pv8<?4y#eogQ4X4;I0E*)2DZs(bt&xJqmo47- zKk4=V|HC&fplYZhaC5N0gqoP}8wg+`q(xTDDlV2ewy^kk%xz$>l{Wz4c8p$8R+fd- zh3C_6arDXJ9v;x0QYsRu5IG#_0{^RBKAf{R;rY#8W;;&ynK^8{Dm}0-u;b&`BJX^I z`3^9tz|HkqFa`9!^1Q3zXj-iySG~i*SeHz`Xsj{ZukZ^De>MsK<40(OhWdILzHI;} zgF~NrX{oGakw=vT+iZL(sCRI33box<QI2`Zb%%NPF1EF`b(So<9WZH~dPhR}K>e2v zR~PsfS<jY5?1|u;T3S@p)WVUOvJu!&O-xL(W@kCOOG}J1Y=|vnY|(Z?KyySIe~<ni zd{9xD@{dvKFu}Lz1nv#PZkfcVq6|)h#N%e2rgI&$qB(0E^Iz~+;CVd~N<|dK1zudx zIRLC+^K9F5lpdUs2peZORvbHNFzPKE&wH`3u-KwR6mE3+idRlfOfa8jdz9i&EU;!I zX2?)T_8jIo0pk_uQbddkZ7-|rr{8CgVD{4hdwk7quIVBb(J20NXY%w$R(U?;I`d(C z6Eg<}Wu?~(-!+gc>8Q#P>1&oJhk6T>%BQfaAA6xplsRe6DKECv`#7D>GcWR%Gz&z2 ziH=RFNS(;MVOVZXXs}+Rzf8^KR*X?rb{L{79G-m$I_oHq1d?P_Y&?6)Y0H(7K+31D z1Z&`PHqX}wu9WLd(3$;MyRZ`hgC=8sO^r&}rIl3$yW2IlETKT+SI|w!co#D3v66~f z-ID&=C36e>O5gZ=b#cqSCPj{V83x(wje~X!7qY90V7uV<(H4awu1W#*I51`?Az`P0 z7&`u+@nZir;26{RxKxaK!Ery_JJvAp@JL*J=%_ss&#l2@H}+f4$@Gp^Bl`3MH)1SJ znwa>|X`z;kgNH|+cYYu)sWIl3?n9i{-~G&N9c~-WYwHyi;Z~=Uyj-a#XIUFZTUB<D zRBH?7;2ljGs?gB)2r&O{vvE3^MBx47k-^;;Z$ifOGnIkG8Ov{eUdF~rHW~|*L}@ux zf`T!C7oCdf;G;{SU?IV}m>ukVyp)7{e83zDrv-Pu@n@wMqT|7s4nLlSqk~RgPXR@O zOHbpV2QNM(gh?3L=HLP8|Jt~`6_WO2Bz1Gr5GXAiQ0&T%oGRK?EUEgG7PQ-bNI5bx zTPA=qa?+h+s21aoKZ0srZgaDY|4%)s9mAj}3woz`__Iua^S#mfG=JV~s>*!Av^Zt# z?U}yqKqM<$D4Oe_XZaKg8Ur?B%IPH$9xl7?Wk~e8-%S*Z=%`1?RYUuz7$aZwGBGZb z5tXeE%qz#orYR6-98P_d9)-ZuiYG&Mf}LkfgS@@o`p`K+^Qo3PjOe_*<o>#>M}e8I z!8#kDJij=&9BB2!pCyb|qd5d3AHttM{`_w*uNBne7yG{>5Q}^tA#rdFB_(Ji4Ii_0 z7C}}Ge=fc>SgkM;S-=pnII-J1K-Bk2;c_bS7#66tRa7L-R_clU5&5H{YhOPB>vl9b zIVt+^u;B0w+`gLh!&BoB!sfc@79L`bsY&+u+9}fT5-_0=ty~1bNk?QSsdCZM$?nxS z1AxQi34hm}r?wlltGoLhcHB#HI^<*k1q8`)T5M*fSUtxK`}a*u#19{0S0brIoR$X% z7lcnNEfae_xR1nm2_d~-APsHqg6t$^gXH-4o!eXUCIGotWl^-}mx8PyT)8}n963l9 zXneZ@evyYFz~ph}#sT|4q_Er4zYFrer4d|r<#frg?bCuD8bkwjgA}AKN2s~&`w-fO zeUj}cB^1?_3nAk9siM+vX4<9Z2>8BDN7It8yHUb0kIJVPL`$KC72mby>Yq0Qi7A#X zyfN_W&GC6`0!OhiPRZJwn&wo?O=-xK%dd9sLzJQe8c8rDDU{Fa=Lz!vm>lO*faGW) zPxyit>hqp#x;&e@Cv=FGLq%H|tCV9!Nly`2yBfb36&{Wr_;+x7t5m=Oa6zT&q|k90 zx3NBwsHj*9YvE`%LK?au5(<<s8N1H<hi8oN^gbbIZK?A>&^k7ZPeEqw^~5I<1M@&$ zM0tCG8@E*(oU1cm!ye**zd#_)8*$k_Wje2dBk*+i6WS+(8)*$&O3E&fW9l3O^4)&~ z4~5^9vPCdKX2_z#-*s)_@ak2OyB9>i0KVl3=QU5dk(;XT-4ZTW2;^yPLF&615gE-3 z1pDXTJtJNP5*$_ULF)L4?Z$e~UJm*mXR63x*ZuK7+eb%YKzoGP@1{0n%;LOP71q_P zRuoP-ItsDo>8|8PLL?CU=@U(KWkMPxx23S|s^p@kN|~g(>a=acnxg9GP^^UQV21QX zkD{_7qLhCKl7AZm0e3%e?6BniN0IUnt@uRlUhd%v6}B}}SV69>)_Mr)>gvj~{&bkw z*ab&Tw`VM9ePb5D;?kLVkUJMPCgwM5tm8><C8cOYI0$rP2yr{rpryywfk?VAuSZ?( zKR+hMv%4L4wAIyR2xcqu0|VVaOB`Pf>}cj}LdD29VAjvG1Mv_4Q*rL&WBcap=eCEG zKNij^mD9<v;VTMfR!6U@pHR+EY0<a>#@t*aW0;O-k+n1|)qdnGaw1UYA#v9|l{BmW z$>uYOy3N0)9sUKFfh`bpzz!%AteiLkoIeaRH9W4|VBUELvOWT8rq2~-p*sMXe(<+; zG~qCTm{)jV;i%jW%%Jgk4-v6Ib1!2eO#q(sxkI2RSMlGUB2dqcM*#<UZ4i?9Sz0*E zcig|*(JCSR2V7}tDqns<f$A~sQc#t#n0aIMO{ecm2RC%xzTFzpi3)bq;>?V^f7Pkd zinD|vRzScJ0h37mC(e?2DqKy?8QRkk_3zSPW`;iOyUR;#z8AKrwV+VA+-%Wsn>wDm z-v*<c67EjQA|e?D?n-|2Et-yGnk!4<etndk6a1)zgTL&d-}r`q{|GY!7k7Z_9Z%3( z8x)i_D+sr<zgyaL4<oCfK*Pn=DA-@QO?md}U^^jcF%X^I1<$8;c)R`wx(n|cbbVcs zGwlAc8g{vuIr7m@c^#8$lO;Z7+GLtGLoVwDg=3hkI@&hP>s8S4$%rJF5ug8l{-r<- z+`e7!1vd{Fgwk%!Wj&g|(u(+W*vG$D_d@u~IBgu5znbte3x)R|!-S8|#oMKDv4@JV zkj{FK(qbvS)DCJ6CfbP908lVGz&orDT{PP@%F5?tk$bYli9k^`4@HmI$mjJ;8H&d) ztqQofP|*4o4ES<~hh*t!j43!cIBCsPi<O5YHY%=HhZyzRQ<&TLJvNj!_!Gyd<TS4P zNRMh&Bv<Z|%KDzrE^lry?sj29Ln9BQL>~?&#e#a;nopZ@5&2>$sq&RJ_bE3}DTI1O z#xj!SwY3Wzs-XY&A(@ACKpQbwA>TilHt<v>w99&%Tjt|D{+G7<f6WA*L_>Ji-*@QA z{{EQ;{o7M|={%A3$oUq{tx3A#KkeeC8X_{nOuip52Xbg^I6E>j&c37ekKN6op^A{; zs$hH!kFUNytob1qJ$>NrsDPqbF5uaXX9Mz^QzvHve#8p9B&&(Jd2VILgYPcL=GLc$ z=V#|FQ9zyJ5wg0Natc&dt=tOomQN??&`_E*&^MG^AD60_9*7K$tO^6;9B4qh?pDKz zPzN^7&N!0K7wmu<<^SR9tAny^zjY}oX%Ojd3F$6rkS--ey1N@hx?4J4x*O^4?(Xh- z={gVl%$dD^-|X+qIQ%U)&${omu60H1_ICQuz~qDc;izu&qGFSkhnZ;w9j5w5?VY&M zO6_>Dy<~V2mKZ9Jg8xg7`QO02021Jv6!{7rSMd?@*rEEP>m&Gx%E>=v0<wK%B#oul zc;bA6+!4|laFZBZy*rXK<_@p&bpW<uF$LR5pS`ko`ynj))A;xP__oy51=#(TQ|<h` zsIG{Y{KFguVs@kH%qz!sOI+C_)eU5=qtCq9P<O-Oc96@dQoK_%zOY&Fiw!!fbHdPL zmI4tGQLR+xETnl#kki;RL;Q8MY9#|0xhRa|kB_hW$n=3&R~+U;a{UVEu_WX4PwarD z2nBcm`v8ikv59rLn5a+;iIawAn%b8U9U1oBzZ4@-r0vUZTd31}zZ*P+f|cN+N==n| zOh`^=PBUvk*ZiimY21pX`FR&<*&#ID{n~t{b?uv@xl$^Q8gqsi)^?_7$YxKE9ED>I za_9<Q=iL%k%9-TkWB^|vzc@WUoy@fXEEL@L71KR$#N0N6C1}X_zDDjM&B31CJP(1! z2vFV2#f3lmn_|F9w{+4{Pfk?_bv+%a=A6GY92Mr?Z>POTKSq)1muOI_Zaq46<`iO4 zWMdXEbOrVy?xla*fEbs0ch9Y&Qln|9tX7=gXB{;YC(_l3@fj4GS_UzW^RE@n1p%2D zv~OT>ZR-=<jW&%L6ck40T-k-!bAeD(Q=_D>56XhWBXfe4Pv#4MdU|3%T9{pw#_uV6 zNDpur3D+?35lPKQ=sJla6=9I1ZR##WsIyoQogrgs55qO?FMFDbT#HVfhO)zR_;5c) z{CxGyW};9-U^~@c!8#121_8dz1QR*cfS>04h*!ihM*@SkC@?wjZ)?*q3j7e&lmvJd zkwkm7E&Mh=+a#?k6=UuFFp%eMNdZezKr=yGIGb;wuMb_S(^Rw;gyX4JwK)(q{!<C> zpd;ik)ASRDiAhQRLnF_p8=t&?Z6F|EO5P~Evs7U>$nqp?Y+rFKnvu(?v8LsG$OWcV z%-0~xwPP_g&(F^@hf4<7T+X8~nF{W@d3U(2T{lKg=**7Pd%C7#0l#FE?x1hac&g)* zV}h?jKx2t$hD86+RLlrEn4(6dH-QR%!=m&f1<A?uOi+2pn%2ku@T=bxB+|b~aT!mK z&)d>seN2=DV1TM46pC+vX+sL4T_K?4AW<y-Auov|yA?CluNo+c1&2z6M$0?9$lw;- z6eNU!RU**ot11k#T|t-*S{vEjrCM1M^ZO@K@IR`&jvOfNrAl#mSV}aSFPuk}ON*IZ zei|+CD(~SSayPc!*|V1VqAP9V5;%S&qP<d5_K;b;z;0^oh<~yo>+Joztr8L`k5+VG zd|b;mN*U^%Q$%OUyYy%#NJHZT*kt}dM4n)x_SAX)cBG}QPW^mx#xxZ{*yM2Z3#69% zBJ%*df)~FsuDDoR993t*h(-zycRmB)0A;sc81zl=-^b|J)F$OvkOE{?f#n(2-ew!k ze&~QnQ|BoP8%h9H*S}xeDQ^JWNHj<Uguc!<)$I47hZ`P{nkp5;hg+9ppy5cyQp;02 z@l9x$nVFkBH>&0#&JFWs_l4og1cUkxt9Tm)1BMb_=sSni!Oq{W?uUmR8ZQFO+3NL& zU=tWL#m-t@gHN>s{QalGlByl8>)T)#e2w=aN^3kH)w;N@!1?B5S5GS$T&8&Mjw)7d z+(K*3)fcy$hyli3I$1Ux0Br)UqwF)cgWN{%K>v;i{6F0(VU$mPBDKH2IM;gr=bTpf zii?ai2#fE4OTH)<aM9C6IJcXBO0DMySfzwq74n)Qu!V&9`0@j^rroA!V0wT~oM*Yj zakOBNVHqBRFIB(nP-?Ree|**0B7Yh23OKhCS6-}XQ1bD`$fYn3X^hC6Tza;-Dhqu0 zaPYCAy$BI?{4R>L%fw?>RQvRi|E<mOs{6c1M3|}Wm?$D5;vhSfDffQ5>K&w0nJyf} z{|^|ofBU;M?4d3m3AM`}OGbo+Ok`2A>B2%u_=lGi6%A4qRp~lRZkuj1d@(U+048}f z*m1sM-20lte2HgZ#EFZJ787WF@W<b)I5>u{D7I-*U2t`C8~^oAU1|4@jbFjUY71y} z!Q~%yazhZGr%1qRRzOz@SZC9=$eX_`FHeg$0K2jpaOQ4Z*dhckT)2!>K46rRtZHFu z3Yc1`2ls#6NnSd%YM<(gg@Ss1b2;lksHv@=K>s8zXKUkuL-eorCr$v+cp|ZWQ0PvF z0a6yaQ6$vei+oxwB{N%FJIuHvxYs<5W<>$L$lqObz_|Xs->S5kiN*MG!U7)r2iG0e zZj^)dbu?{NL6`IP*J@{?bJh4gV(+TkA21j!BtUdnU<kG|VL|Ea;;dP%S!t7_=8{J3 z;;fn_p<{X5Qc)1uFAMnJpD{^%k6WyrUdHS{<B%ZiE#IfRdzWX-xu0>Lxul<Q-|pIF zhyey6xkhj-9|9wDW#mCUp}Pw`_adl1RyP(4HLjmpZdd!{m>*;g;t(*Yr=my)+`6au z^MI$j&MqMI5O0s`U>|!J0a`@l%Yv>6k(l^`*BHR;5lZ2-%p4s>NuiK<@J=~Tva+kr zO**{e4}$&wz<E}0aNg~;AJ~ZujgU|T60%OhbV-VUe(NVxj9fEtYGqB5U_jMXZ7Fxa z0Ncc%$uXJr%cE(~c(>;lH+g%vl(H1r$jL(TJi^b%x>6M_Et4@r`ENr@OM$%+xC6Z_ zg=|*GIEaW<C)Ih?)uA^#yAuJ(DW+GumK4!zqb9+_-emaCBJ&ECV``mG)m0qItP)Qk zLekF;CLwBMLIfcerkCIAZMS$Zdc{)`6F*8lc(aX>DyVD9j9~92^j{D(j${3650NSX zJS3y~;b~Y@B(SCD=kWfNzfEqa6tuNPFxV|+Ft?U#4ytKr2X1Kgp*ZfW4ZGS((VOb_ zK@ZEUV*(ifCy{_GZ@M*s<$aU$j)Fv>rQ*~qJPrYYC?HeDYF~hEUN~QzoE2xle*c}m zRI4#_Dw)zUo&5H;U_zgk)t<uDz7Wg3_SDL##TxZwImz$wnL@$S!^7k<4mU0)#w{kA zT2NcX;SWb8tIz5qug_WE_;^$-Qy99HNM>_$+*)keeX}iokOIuV{(4w%P2oF6C{Y`J zNI^lt7`GFXbdmN+iw#MMP*ub}YKrmUq^th5wY8#q{#bejY>j#+c2#xN8-mU)2$+Oa zue>P&M>@JeQ+$csxtSRhlIX{@ke?C-!Lj*@TB-U1sQ8CR2UlZ)PJ%Xa<1{=}2}UEy zL%0;bEEh`w$NM)pXvfeHy6kPuzv<(%iwo0zU()Qc?%v5NDJ1i+lObT02W-$@@xDOw zqT|FxN&avOv#X8$_N`YKhT=h|3S!?<Kwx!EY%}j5ZSssO*lTojwHFt@@qy3}lN#gO z-+h%tuEUzTx^a}&ANTiga#(}N5jlBzQ-3co)0AMvQngzj%o^|&?9&hdD?qmNa&=f^ zql(%OSOj;BSN)Y4VgSt_7~hSKF8^4QL1D|V&deUZrkIe;kkI|>mEuAG{EuChDFZv7 z(St%lvV`Q?!gsl0fNt`ym)nsKq6A=am&*N~Cg^B<X%Y|r(3C;qac*vIp(;#bEREGz zK#I_fUsmZmCp&;HK71xR%{2}gWnOVOZ}(b^u1;IjfNOPjVB81mzN9XCF3%&N{Is`I zm6i_KUt%wo6F?((K#!VauQnb7jaS%cZ$080000&HT3L4E8B+VkhAu^t?KoeckfkMi zB0(kNr-(g;UwQx9Yy3ocEA~FeUvY9IXcz=vHqfKx<`FatzGTK8wa(3g(>6W3`zP3} zmSM1GIJPd*SGeP1V@pE@^AhwIYm(wRCl1{-K1d{&AAc}CEue9hGR<hw{}hk)@d$m$ zP#*&`&}RCM0&ry-QSfMniXqHuX-PBhISR#QqUqlQEF~g!V9QU0ejd+Xu-Q$2OHp5J zU`-i<F7OmwDxtvU@)g46m34G<O1B|^``;(@|C-!~CEDja$VBweY><3s>p1%8!&Kub z*Sjc*e{mi8<>rdTGW(E&j7QSPOn0{|Vj2nyqi4My!~13;>k*P821-vJ)<6Jrr>}(O z;L%;_ZmD{-1!sD1`1{?;j~K#rh?C_8AOwq`AwL4WGnk1YWdLB{5n}A<C@RV=RdEov zv?T&%V>Pna@WPj@4<7`Ic4%lb9@7>gCCyT^q__<SH#Xu84vc1VK%emzb97TAV(uUB z`&_K;s6#^iJF@fqHpF|;SH=t=I5^bAKEa=Eh1UBIFy)e7`2F(ZqT~4ml%9lFA8t4@ zL${y(?Mape#~(*$XZ*B~3m*8I+CyguoPCX1TigIuo$_%f@Wn;$gnqA*c(3H8Q6Sn< za-xxqppuhMLDE#w-f@4nNFbtxrrO@|c2;3(tsdFCrEg`McPEWp%Hme1M2jt-0(tIO zFYk8GoJ*>EF818pto%T#)&wZ7jJLP>ua8m9&CN9>sJKbwrHj;LzlJh~HHYV#)6TXm zRg{$tXL$bP2>23Fb6r#V|NhtS5CX~#zJ0PV5Tn-x$#*xw2=RTbb%;fzukjbLsmTCk zI%mz~9HG|)&~q{O4sg&2HTXfIH&^e+DZd&U!=3c6<~b&PcCo>b{lm3zxPP#k5<=?r z5XP;MxaIF3I4^8~&u$+8?_TpW;+#m(i;R*Ixwg-)uY{DvY6-yK#R4O_SLZ@~QyC(N zBTX*1g1Js>xyUTnT2+rGm@C;*s#7G5;6WpEbCJNZJ5QF^<#Xg^1E}F6WN7X}3)U}= zfBmJ_H-Le4eS;HXS};LKrurQUL?4-Lle*q8-jL!X;Gn^Apr)iHiO*4T!b-N7=g-`r z10|l_2V|N{W<U0{TjzYZa*St`MLNc$`kF^75)(#0arTXQ`WEL%Q&ZE_c+`o<#is2v z3>{-4ErBDf*QWH=2VyH=+3Vfo>2I9Jo_*_X;f}t(K<>v>iv!T!QZ(c`&3j`3bhz9| zLAOK??yeEw31^r1XnylCpZ0*AeMZCS{Q!!Okrj}?dZLj4XKxO9@c)^~+<=}@$QsY( z^a6%w{u>QC5N4#|&c_xD0gr&JuYan-k$M=4bSA?f<=<*}1xrW6H9u!cVE-8sbiGBn z*f0=a;?DfLT=OwJFTN%G%#K(tokjboO4!sC!O*_Oi9g@^Y^Ae-ugAsd3l1Ai<*jZL z-&`u1lhITMv}<D;TEyD?{^LLpX5WSTM(qhq&hIXb(Qjl70B<($Ynra=L1;mNNiydv zR*XB1`=gPWg++xnSIIgC6a#js%uUa~UxyG-5pSbcUuDlA73FxRW79J^c&>({Fqw$l z$-@IG9FM<)j$9ozr#AprquPy<eevhl)9>#iXE9AS?B0uOC@56OqCm9V#yA|p%_}f! zC$~(Uh5CArXR_AT0z#qtiJ?4qHO+#^*M%k|VFepW;wG?nLG8QV-j@Te+b}K`DO3dH z+;>+W&2MWI5xOA_7Qx&Uql!)QNjcfs)B6}WXL?X0lCNi*pL|aK^)J)@@`jRl=Y5;l zhM~8}M2rk#YrsYm<mdNOQVLvv**wqkSZsFX&yPN<G9~<4hYAUbF6tod5RJcCc)U}k z;B9|!G>;&XBTAOu>Xps>=?8lOdJlHnJSi2-^(r^@6tFZ3%u6Nw?y#>QoUv!gPa}sd zp8Rg2SKNl%&_dmqI+67|h&wfmfIR{OBg{DE{N`p>x;Uu)-TmW&BGnvil|JSYa6i>n zT?KFvWWD)c|I5F>n7|wRcWUN0qZ27fbXX}vDHfWEXOT-2{4X&i%=633-G_b5H!Ae` zaykOWL5ty#_~72+v56V5uQ8oanvvo0;%Au8wAC0(ehx=BMn9O$0k;EpH!Zs*&Oy9t zib>$>!1JfuQ@My<>>m+U9UZWQ5K)lr6N%m94*~)L$2Ax^BitB0ZE589^~#&;6obPA zU2>2QtL817ANoEWeE48k!)naiX1pOZlM*RChW=bWIpae=i-xubQX~(Yilf~!1s8mk z{u-9wEsU_JucZ|xo8*u@?_1W~95OgacUKt`5-LOM-e)zqSQmS9HdZgLHT*AwbN-vC zd`dx|oE6=~%nIOi2Q&UDFDIUp%J_oLVPLhdJ)}V(G(Js1@*U!r172EqUVeRIub#_C zYK((PrH0vu-%`r`V`I#@Vv9?QfMBjPF2lS12i^XUzMxot19f5LP$3tWZy8X)s~rO# zAOHMfktQ8;xMqSWQQ{w(00@^E)-p5;K%kYk4^Rkdlit9z*L~7AsIrC-J`6Wa3b48` zf_{Y=>CZ?=wg^<cW<c*;W1m#YJzA>Ht_rEEv=^GKBN!#BO;amh=*P_&PSV{fVU^Eq zd%Cys%>2qDEdULGg#`<f+1y_>YWmb(v@A&9dq<k@j`b-yz0lCnWp#F9c+uy6@md`p zH&F^FB(F2O9mMp0MCHFa9*R($MJP5h$eCEO=F^|KWt0e^K1)ooYE4Y=t{jYB`uSfW zX8(gu!}~Vrruph|-;#_E*7oj5km~3(i>b6`W0>;mZnC9JmWA5V@w&gSt@pN0jX6fO zd)Cz0fX`gKP7G3QL4oKHmLN+>EA<mqH8u##K_{1}o>&{(SbDsFoC2amY8h`YT3eb- z)>`@HnE7yQt3GRVc5JNkc|bG2$bgT9N-HaUXT6$~nj-rmGxStl31|yhtzT#@3{3M* zzT>CGB<Yc)*_^`rQZed(nMNic$wcy%!t9&;kf<ZMm*xx`e6eD|z{n9G$LrWS8=2_& z{J;P{JUW{QBxayyW-DHWf_kE*qLOxGj*pfP1G&21Ctvk(I6-``b>rXJB~lR=kU-2{ zY?+Lm>5t~&H9IlR@cIo%uaG1dtgjpKIW0j~UM}%B*80UCJ4FA{tS6%RI8IRlv;tgs zHlS%0HORpgz2?FNDB`AofAIF1H6L9qoSKvr`pHTxC^znmd-jo;g6%gCmz@j&<oGn{ zxE@Ie9}P{n=`U(Z<Xq-0Dg_*guT53KUA}Q0QNRoLmz%fF9=u2z7-X0O<KvIqZej)$ z5)Sz&?dG>C!y&iQoSq<b{Td8NarS5n^lBp}ibCFu_}buPcIcW3)z7OxVDLKDe$Z4# ze1MspQr>^i(U#iFc!gHRdkin)v){#vdAX$~=HYRiJM{z)vocNLTYJu*IZuH6E<{bC zluo6{>T`8GCKjmsHMF&5bV}|51Rn0*pC}T*jtgZ5w$~J5?ms(caDrP(jLXQ0ch=hX zbnfgID|Cy=>pK?z@%p2@?TX+!dnR|O#w|><KQnxp>{|}`8x4+$a3hm=lIgClWdI=S z4@8XP?Al}o=4NIWT_ubfqqx(<?5@`w<h`aX<~L!X@;IXU;*t4(=I7Hzqy+}ujdn{K zBn*qoigHrZ7F2$yxq<&M$p4xzD6YqCaB`dL=GuaJy1!zjnQuJC(W{y7icp@6jZvZ@ zw~y0>?6x)U4Qrst{ZwbUG%QDV9Wd7pvjoq^$*Jh9o@g2RlLH=y;<MqUi`!GByXka4 zk{|1e{oTG|5_lUE)l8cW3;KfpmS6hucCRVFlc+@1!GVII>5icE_9yV@>7RL?)AHXw z;im>$sE_ILxuHQ0bb?1U$0nD#r{bp`09l&E+|wb-&h{^%f1FhBTaSyw6n66&3WM|` z5%z|zMsa?bmLEcFo}Coz(PW{sv-8Ag>WPY?qLCzb@P2Su*mx=gl5F?SK=jWT?8jq{ zLzIMV{ATAs=C!@bvr9;5sB@4NhGDh!nH7Vhw|uDst#Hf$?CdZ)d1>oy<VOx*VBH<l z@c`S1iE*Fk1wy#8Edmaxl7lw;mf~e;tL)69IFJqbfNUvT_R!ctR~OPafoA<y^jCsy z=aBij9aJ9^d4$$f-q<evr<0mALde6TqX^<(b0}maxDn$*?YJ;<I#p3GPkl`$=j+0w z^P|)5U`FDK%cENG5x%$l&Q5&ZEJEk4JW140xOU?)U+Hbwn>XlwmLQ*0Aj-#Uf=*Bh z2G<r?47~O+eVpY}VU8YPD4OQfo9l3%sm~HvnDfctKVJy>w{c(o@8I}^8I)cH;(KKE zQ{p|fPX<-Nx&VL8cG7{vOXF6NG9dT(L=$kmn>8Du<RSl+261Snn_7jJO-Rkb&W@`g zI~l=ggXaN~McUEt4a<j#06Tv@%KP;TYH^_V_62Ec6RW~}4y7~{N$Ejv_>V1sR1B6k zZ%2*D65wIe^Ih-r7^dP18N_^rq&64s=#{3&X>p=nBHjx}KQ}V|6BJ~lAL|f?-B(nu z&IqKRNhW{R4be6JV0)a*;+UXjWvDqTZe}7R4na6yN<?O;!o#Du*lXtV$3+PWW8?Lq zSiWQ5TS@5|^;?Y%$BxCTwEfTKlL*1_q4MUb*Pp4j_)to(E%~s`amatKoV{~yS6`<s z!G2`j5!I031L|@+?8>h@HheF0#{2S-e7UJwX#eG&_TR%~yBpN(_nDG4R94}36_^}R zea!qpWWz4}<SY2!FoBcZv{M6XV~r}WmZe(yZcE}EC3vjZxA|F2_@kX&odvBOe@PqK z*lm}2pq_Du9yMjdrrii2fHkWr8~z+7W+1peZltf6?vqJhgr&+r<Sg5S=TxtwM&do7 zl>tU-QAQCo;}JX0QS`vTRXJ2jO0iVZpK!(<1p>Mr3Yjn9SC;PrG80-N?J3nsqTKCw zYnmx;PBj|OBZ<ca7++$kF84T%*FR5oPnaLpEKJXi=0et4Y(KtJJQTk>AY2OC_iicp zJW2v7W&3gmx}{U^Tg=3hMoy#`k9^)CDs2P2ZvYQQ=TDTxzikO1Y4Oj8+g?hppMHI5 zOqi;)UPwOqi(FaNg`j17?+@N5zvc2E2H{Kg1}i7hgBCToe&QJhUi?QvXYv3ITY;B9 zNyZQYn=M;5PR@eYuic+ez67QGu9pso@Z%Y3&GnLiursa)J%<7N*>Tf-jCj8xqm9@< zAi$=@42KzRb9>)jJiK36*mI62a@%A_kzhm6Kr*IFG=XP{*S?B-QZVE8r!^Tbr!B>| zhRe`1wd>7c2-DOMPl9*&VZ+3d^tM6!Cs>MF4u4oNw$CGf10kL4yAVI8UG+&CY~%zX zOXH+eD5%42Mv0kin;&kL;wdurV!8Z6qgl|i<GH+KGq@8qG&N0*)cQQqkMj3^ko%kR z@_x(o_2Ea5On&{C?!J6zA$t?olQ!3Au+Tv9ydn6UmhN)7c3MK`z#AcCCXFEx-j+@H zd>8vcE9KeA%-mei3hPIaGzlHuFEx)BDoScpHMwqltLBtdmm}!^<xadI1uFW{rkl>{ zYi8&a1RL9|EsV==eDed18H#t{ZCX~E?!m9`u{rKSH`?L}AqW<rxUyBlS`oM~|DP9t zDKc`<S4WCH-&reb>pfzA&4D!?9S2*<{pe#ty>nu2H+o?DB{XqO8I{_;Y;AD|_Mhcy zbIW->Nb(6WP;fPj$~*k*eEKkk5jdufRN<|nID8aIIrx?mW%x*u;tdNtKUiNR#2a(M z!nyQHH6PjE!N8i~LjL*{&K(v+K40?vsxX*U$6}??m*=h}(g@%8fhVr2GMvQdmMSVe z{mYP`XLx5<mm6`fJsjrWqX?ZT22LFjWBQgbJEv2}bE|JZ*rANmT<JbwTV$m*-Aq); zlxJOD#wJ=Q$->FU?9HzIkf~p_E48DuUad+4Jbm(yv4UcR2DJ&`Vg3Wqc6xh-c{{t6 zPGvHKm3O7FA*6bOjRc_p@c^6CGFHfj+tDoB`#F|Ty{;$_@@tFX)$Q$^*Kt|71h>zs zR_c9oG<g`vkq07-h(98SH#=C7m&qCRWT`&TTS$3`YhhwS&fRIxMBCx^>IxJV77efn zCMge+c381S8UTr5Gi?lLv>Ty4UREGuuKZPe=$Iv#u;mxj<LKZ-M%X3}hxID0ini(i zC0m_>dg61nDY(9#moO2DfH3VYYb~v;@ROtKzVFihq0ZBMJedo4^(8g_u=s=Zlnhgw zNd5ASk3{vk%1&;8$LLLYK}pH4QLZZq6&01kLYlZ~URv7dR;?FoDR7%~X?1lh<KO*{ zHBKu=@!h}Z|D#?ZpiszwLxS_|sXCPab|DF`=)_xIAq|qCu;B?c3H|!II=k*y*ebRq z!I?H90==*CL7ZHW`&ovs%*fZ*ScD%eU;X8)vT<gv>~2kAy$8Ph%%eg<1a?E?jr|M} z^hrq|E*YV`1cvsBMmDxi-QI~X_wuuy6IsRRCs1{0IB@1M;H#s#vTPDs<j=0KyfFJi zn-kUIY`h^1-&}Y;U=w98dp5bDY$?L|T8$d0jO~O0Z>$;+q%8a-@bU)(W79$#@#;iK z$Sh>+k3cXseXCCz2=JjMOZbcr>B?ke`9luyZCek6n6rbW<8o_wz!P}r=chQ6omm9> z<@^jC&rmZxVWNLDx^Qn~U+4`z(_1o<>zyTyrGCNowH7S<Dh^v)1cGb9fg<fCV2Hxc zf3V(`6j$f8g$go&*0f|$qT_wk06Hpe!y&ndgb#kNtDa5wE!K>FuLBUZ7w!O!rfJr& zL=azJ!eb9@eM|qf9Clzpq~YekkRk)rkjlQ%{-U*0MU@(s^nFw&5AWVWsa9$rp?0lo zTDtXXGF#fyJZ_I<EDO=3^R9vI;T8+IGQU#^&T9_>1Tu^T>1Ts}5{>#@azrGy-Ddrv z^gr%)P~_rBpkqs&$*?4u!omf+O9Y&a1eo2CG~u4W`bkhEzicGmgM9t8qGK+_r><84 zFMmQp=y(iO={bh`4nrW6qE*RG80R0S(}!8{TK*J~h|BBaGXy`)Ijv+N)I4;<dDR<p z<9b>1U2TRuu^{iQ*~rV2riIZn35|%zUQE_F{AJstJ4f}0Jb?9Yf~T8XfXI+dP{(Wg z3m;%%pJ-Iz^ydpABRvWVKuMZv45GfClZYUYJ?IKxwSV+fh2M5N2at&A#$)nANmPP< z&~i&tVG?qeNgaCBFp92jRvp7;&VuZ5f34Aox`t8O1!i6pr!m9l$=<LuQQQ;D8pA6$ zvyPT2rbZO6$hTz?T7`dmg>GSu(={9;6Rln-3QK)3s|5QrryXp*c#MTo){`slC_fol zSoOyInRQyJ9bOtS@kf#3R<Fdok#C5`#GvzKizkM*mH@`qI}449eJC@t&RaTT?NuP~ zDrS_+GrGENs%0$J+dJar{5-a?PoLyJQ4Sw>^v`EZgr|;#nc-6Kl6aQEKjN@@O&;JS zpAQf)^EI>ubjQ*O=x7<I>yzG#2YV?_M5iKT{$Mp~6oRQ=VhNdgjKpCMiQzI!wg1EW zRghVLn6Dz^=6GcQR#bH48kXSzaIRb{a^xn$!4f5x2+ON+u!TQA;GfRht5Os1g)b%k zUXX%_N~}j6wsL%~Y&o@<&cPj2uJ}2Bk3$o)uS`{kDZe9FicN3&o5<$l<NXwHsk84@ z09>)I^BK67hsH&Lh)p#3eQFZZ*F^7!<jdaI<Yb<QZSPO}E4Ko<)^k=>LwmlWm+7qr zq}mP}-)n3-=wpuMi|VolME2toU*rTEpWIZ%erw5*k=%B6G+#U1%UflRC3>IaX!F~r zG}z}&0TB)Qb7#FbB;UV%`;wpD8dg+%LD){jR|)$cC;8{iG-%juhom0(8ZRObAPGiJ zOBE~)6FayDdJ+6!r}ihd<XMW&ru_ZiY3;c>uTjVI9_HpQCt!ufXb{Q@LJ|{OOA{sc zUhhjNx%}0iN(hA>^OECdx{Vio$vU7WLBRk-^%IT5g9f1IyI^H7Q>J^)M_#WSlNMuX z5l_Om_W*^Er(cevz;?MS_g3G;gvQwNbAoi+t;dJ-kBL|@;4mcH7b#{6KoWt(pyj}G zvKlX&o7)qx+j#Z!eVcVp65Lz)o&$LSG)dn@2Q{7^1<Qfr6fEV|UCh?^wr5Ddej5>L zR$0Z(%GMnB%1sx<_HahECaVKLMDo0j0>B)h<@P*+N>J-BGaGNtu+VN{dgJh;MhwMx z)bqa08}!-==2&ri^c!8CCBKOYBRy+-<dX%AHn=^#ua+M70YQbT9OFM8Pm*;HU@2rH zV1I042X#rVqHS3_gMLD#u9J9&5zlS7Xi<h~-VB?K^H^2Ik<60(L&>_nrp9hic5k|1 z&XE}lAFDH9Fl>XIJBDwitZ)ZTNm*&wdZo%Xla$LiN=PB-YH~QRQold0khO+UPr5Jw z;2SCcYX&nj@bUC+j4uTX%NK6)xQ?ZRKN}4VO%3$j0?AyiJo&pEyI5=?grk#Ftfp6a zwbQ*jkbDim%0m%|TcjrUIdvi->D@-a6kpP%d}L5mRTW8mzT+8OOwex=LoQJPqS!fC z9U^Ce_{IHN_4MqGt|_FF_4%yZHRn$)_csz8_``&saw}(E!TrkMIqGzFj)9Pgm<!#T z<H8!32`!Cg8xE<1_to_oTDIuk^6>dOPnT-d#o1v`dui^l{EuMr!Tu?7Ni{W;G|yG} zdEAzkJv5?!K(u_Rz}L$61ncuK`-V{p)B1Rg=jNg4Z&`^88b1my15Je{r}g?n$u7q} zpa!-H`KH6sJiSEuZ1LJXElAGZ63ZQ<uGB1Hr{S$$TTx-7Zh2DoDE?cb@hc}Wu?|O_ zfmw@0kOt$&sFbEeAiLP+6G$S`%adOk{9W|7`|6TXy8cj}Bi3*Pm2%$j`r`7#loedX z)<UXlXhX9E(azr9wf`u2#LVoh%hMW3<lk`=6(zDfVz+ZAxYM5=2W`(=u5SCN@;Dj$ znYj1w{Mp=B8{$%dT)wAGhLQ2Z%u)xYPra+fWm@8|t}l)&_Mgw;AqVcxcM{EOy!c{W z?TyD*+M0r?<OuAaXm@ln+(!?RtJlSb%G7?S#lM>#%<{N_eQgpa3?$y5TuTBBG4V87 zjQj@gNbvuo;C+1Fzkvqt#w&B((W3er+kJ#C^~kC5OdS>TWiz@=3&JIy_jXRQx&kj( zU_nnNM1+J=wZ|~y3lj$%ZfRem0lR~d`3ycb)k2LwWFM0~5kzgK8&>O##~23}D#JH7 zH%;G`ok22w^G(5i0{|7EhS6N6(5Fj_g(NZ!%50?q)(vfL8wCZiic@@N*4)Z0XJ*Y~ zAVRc|jZZ&^^nP+OaB7`YswTJ^vc~<JDYn!zQ$&af$<Oz`xq{zHR1RO;_#T)ZhV);n z#3%zt__e-$O#%TnujwvPj2k5gWmbC?9UlQFjuu2cE$vG`nOd<O_m@aU-VCeflUfQ& z(&2IJ;S4FJmOBc-Y%SafO`RLJ{G})IAPde)S*|Qn@Vl`3^OMp4GF6zN0bLE=9Hi2p zC<t|^OuUE+;9+LY0^fY#rZuH8G{BQbUjh^an)PMQQ$gBtBZTO}3<R>%)5{h*>xd=0 z#ArgMrd?e8X0Y$z0=cxvq#n}&@z2f4$_OPkUM=1RtMTYWZFyUp;Jd0ymBV?^f*grY zc?-Hk#>3fUl)6e>EI1vzb7CbaiJX>w<YkA%!=u@CMOWi&p}e6X7=XTaE+HQaOKWQZ z@(>Z_PFwyAi+~4LMo0+C#P$FyExnfaEOdkX-l+E1hDRqw-3`(yZF6%NftZK3#pJ?2 z&`^D7Q3blH8b4Nr4S}u_cg1FEh0VnVY9xcR`c^kzFoRpaYBvY~_Kv_U{JJ8+e*v#j z=NiUQmshVFCLrGJDqj6LZ0h5LW&KkKkt;Z3aHuH6$F_1p!zohOZ&MXrDi%~(m?UQ$ z7`MFaCq3{^_rKAD|5`s!zje{IWpFvnxW2Qq*chM~R;0|L?4)7GWOB0bJm<4Fl9#fq zV|<a>f^3;k88uz6UGSIFQ@wI@Ob+I}kl4P@a!tU8dW40Hhlf9JQXhyozt7bBx}}-c zQE&=hMve;Svqh_M%R@#sINl9})C%;4l1r$~8kG(~NS$QFB=?SrlGD<&m5g!M5yXuh z*ltmowHT)z9!f7}Bo6g%KrxsLjoE%6?un+Pr&kf1NF`GS)X|o!%?W@rp2=oTVRL@s zsb`NcgMb$rZ>r@qe_si753?cx*2G)8J(VX{;fT;QqSIs*x-x4A{xY|A?mjrGv9WI{ z*XT7kPVo!6U5a^uFEc4k#@pfkdXcC8=>~74-RdeEMN7zFc%dN>Ft%1lS?=LaXnnlp zoG34ElIAu{f7lCkc=e0?MEw!wzp@<uyVF#76ADZ>QAPC|z;vVG;-HDHT2Nf)0BVZi zgStJO2+`8wQX{`Ls>mYQ<C7Dy2}Q-}`DxKo1~UmFcURYm%x+O>`7z+9)J)l0ztPF_ z+Q@8Cc6Jv5V1MFWQZ`-t6?nPVM6|bea?d=eX*U6qyJKm%Ff?Y+w)=PQqr4XahzK1K z0)7;m->u+uDirD@a`8!kZsk#W;>|SpFagj*6HrJF^I~H35=bMZWkTccQxQ>7rv^*F zHW%A{fJ@zj+m4+R)Sq7V@N3?TV9?^zyL?+IAM1h5fbZY8)6rTqq94{`*NB{^v>zEW z6}ru}QeSQxS4h4!07;PCo=r}eBT4)tgCCArE%(Ps<7yfD1VVK`Xu}YB9-GFzblQ98 zvL>cyn@4<t<-a}aGnt-$r=qEO7IG55#>!wxQ+oG=ypzfp8Y*)zO_``*_@U~F#v4;u z=)cbwScWM4296l30S&Ed8K!97g!a0WKewm17og0<A{VE$c)kZ@Eja0WjF?{l4;Y%y zQOMcXgE-iju#}UZ%i`0xT!O6h8%yUvN#QE4u8%aYKZ$A=6jGY%>JmV{*SPP%5!I@k z@_(#<8xrb}GZ$$tb(0!AH?m9QKiXn>Xe`>`2`nq-Qa8_E7zWL{b9{h{kJ<dfV<VIb z)g9dJ=IJ&&{kXrkC!_b|96%oNBS{5^dX6F#bg!?sY4Y@&woxo*5&^hy@(FpX3aYZd z-tw^`9q*g$ePv}gLi@my?BkQu;`DnezP3o_@Di}Ss;tiBCb$R8%#3G?LR_tc*7F4) zkr{rl1p+xHI?`t3-tS+*=h_Y<<);ct0_up@k!{bufV#m#J!E`u^=;Hvv&$Zf<%0hY zbOD&7pMfh?Nbsi(4onzY6!Gd2*NK&APIUh_a^3<~4t7VJTw8~~(X*ZC!6_VNfam~I zxdH!sA7Srcq}9ZPq83kf5`6-8ej!ElCB{TXf<PE7GTw0w@eQTr?MBzTxWuMJGqYp- zO0uH^cJU*^y_)xWo8c5GzgE?>E!WIfM^VThZ%!xOB9X}CfqotkqmWu#d*YJ1?H;;f zk<b4e6(VWL4~EoWfg#|l&>6xZS)e&ypjhyoZoIwfnXB>r8zQp6S*$h=#<i!7N-GA} z0awOF?GWhciLXUDj;ODmJeZse4}LyW$W`nE`^9Zs)cQ|%2Gc2?OYW!p{PL+^VuA(| zN?eWeFqpAvU)GD`*Cv6OPVmlU{T;7#vhodE)d1?4jx^KLEyLTAB-+%9*J-l55<CI- zO6lz_nCmb+x+-RzZvPH2fv2VX`1?OWZM4sDkWW<>5l1kzvO<{)lV35?=p6G_YNZGb z3*P~p2z#^J7I$a7q)l{vzk7-6c9H>LOQW5Z<}~x&tdN=-bw~0*7Yh^Lc&=8y?hnom zWn<g9O>38V5umz5x4nVlXP}@^arX{^#2s;iYHbC$Uv%gP56LZQ0uPI|31<zm_;aS( zqmMS+2{}1fc%yQV5q3{#`qLLlPzGm3gNOj-LXfwGVDoW}ComuIrU%?h;&;X!(9lMY zX1!#|#lyIJrM3)|r|zn|GG2|&mg<iTMB)W?l$8g(C614NXE#rxjc>r*obU_9QiVI- z3Ak|vMTTara2EpsAs)U&F6ZTL`MLz~f5U{{Cq5^$zG`XQ@9?r2Iphs(?^|yPzFshD z{JraZk#q01y%(TP!oy}rEsbm46!IJ}oSU30p8em>^Wz)8?#NA8qX%JnX2#4h`T6PT zL*n#bmn4fPV!iRZHuqZ;ItE&n)}+AU^WB1{f_``gWG@jBkg7%~vy+K5UT#i~(r5gJ zv;~S#-)VEf{=z4KfRffwTbHP~WrsCa#>8Y_Ub8kDU^Sh|c)ggm!n1&;p<ttM#P1FV z17ng4JsBu<0MRE_6Veq9E}SyDu>dkB!vO+;z=v((oPgc{P+z1s*}{7=vQEO7p7pzy z<%?Rb<bkzyMNr>?n*3u*?*cYO@$c`NfJK;$fcMDYd%Gj*3MO?1I3J>c^4A%8sfUPE zeuq76)Tv(CB{#VZbeK4b3UCRrvePW$iFLCyR0L7H6l<P*HZp#-3dWFWRjS>fmfOir zerm!8*>b%M&(@f-zn9`IUCjU2#q)m%!X79g;C#F$)?whkNn{ok#b97y#6L23@K{C+ z$4E+ndS6FUW@B)u#^vOMvK938vH`1uU<!?ba;jcosTHPPuVB6e8e`+Sn;WMQpN7|V z0kZ=2t;Siqh48X6D~>-^@8l&yBSL(keNg0}k%L1baQDH?dla%>vf+4z$vwh`W9exc zXXq?!^r->WB0`95`4sM<pk%IHfM1~o9IvE-x~(lbp`L{Q<RnJK9qMdqpWEox1P>HI zdwb$uY)8R)Aiobl!j-<fcRCj;b4+QpQIje5$Ahz>v&}M@UqpttSV)!~Vib`0F54SU zC`Igj7ekd1_vhjGs{FwJ<66#)IS0)rR+y`=P)e8P1GtHk54FUfZqK@gygjn|xFG;g zTwcH<iRvp(=`=E}p}JQExUa^z+&zw336b$1b&U#~Bm`>9xx$hyO!vO(NUe*$UTTWl ziXtBH^eCGZwXz*a80_bTAGPf)R?dpm@Jgeymf&MxWQ$Qh-aSl3bx6f^vyX&N17BT) z9un^``Vib-@j9FZRVxf#B23I;8Byazk#Wkn0ob12eP@V*iBm#GxiS-T1Grp36>ZWY z(cK>;DXpLHlO>`|XcqMmaEi?_D7`&qh_uwo&TcOGJvb;+kPcdy2*X6{s}4V!8wV%Z zyHpA6Wlm4)CU<EV`n$6HmOS{Ad}y}i^BEe(0mCKw$ZyT&dF;-fPH_)u4*BZ(I=6b1 zPxYuJmxi7`Yb?QA_LG_i$Pm%Q!s5^qZ%nw|6b5CNI8Wz?JMY`bD7U0MCjRlshW2eh zr;tNTA7|8dV&n&s<Od5MhO3#TfaR$ecLNF9KW3nYw-A)&In>Ed(n4We*N%=@MCe%s zzaP3|h*kQ+(sHcNok1LyJ{LMn6&2_30L>)x?yoS`c6-e>^Z*F=5jC{ZTTqI@vAWi5 z^l#P@WV>vtotA5O7?+}os@h*AmExN+Ly-IItgOb_caj(xiJW|61s2}zyZifV0;hhE z0W^9a@j*+9Kd5u?lXT%P<Z0w<#}@ewS7MlMNK5iphGYSKD`MkE0XCyy(FdoIM2hI{ z!+NWt5|*_`8PBq)a~G&v!8@+!N8BsC+-}#6Js>6Qddo3(j-A~xuG$`TXZx7{;ZKV5 zI7J4ur|EBfI!qwuZEPRNrr8MlaWNQlu(c&(oZ*Pq0)(mz_HV-r1N#J%o=Z+zcFF<t zA<Y&epo>bgTkKI$G;Q_v`(DaM^$&v^t~Z;J)BrquS3F2&As74P8-=n7t62_u{hU+q zVfNN&+EQWkkv7Ovz8&zlc?+-N;PBnt#H1l1Ie(0m^D?SrGdF#@LOpd(IZ_!A-whj% zZj=nMWoM%g!^3|l?<zAVMJ2=<EIbZhZd0|=%PiSpfz_<Hn06b>{fJ#?+C@Xj9uDO8 zxTEkMD-!%xQktw?b&mxmhaws#(BL2ogJz&XrZDf9%-~n-lg&0MP~X>ae^KdRBw~S> zA<^x9yt6^!`1ttg0bB?G5TAe%xI4EWg|hh&j?Xzbq1j;Y47i3Tb2<mi%2Nq-WOeEj zyz92jEGPgQOxX~@M39~jSC@~s+%9_zGpo1#;W7NB$qTXU(lvJA?7X^eHcWl&-Is<s z1;iEFcG?pB58}-KZ6Mv>s7Ni6dW2~Eem*&5Hy1ay-yNKZ$qoQ-i6aR=%xej$xWq)W z!eU43bt7m$C_kEjAxg=C-$DH*A`zGoLW*60L9mw26I%YI_144Q>0%gOQZ5@D0Ypg? zewgU%5Q?frj>8;Pgd8{bQtc`T<Spc*#zO+o`hcY>aA06X0+xqCoN+)B>{vT<jH56* zmz4_e*aHW%4mS<8<Ve-3O1e=eDfP$_e+&#Q4NbJ2H1;;>DLBef0`W-=dgjLmSumsA zXVQyR2lgQm5nu%<iD^09WYNhnEjQ^lf^KGNUU$w?%{H+kd=4way^;s7zOCPT=q{)J zbHD+u2*nu6#&cLMimHlM783*qBY-I-p8I-v_IQ(iY}h-U=H?nd|IyG`zFjkR`~H*Q zA9bsbP;kX0-**^1BiwEXV|HXVk8>;n=?lpi+mRgJ6J?omVhjpyst3%uLV_a<MZD?7 z#4DmRri>aJr5X>jvqh3C+nP&KdoD`g*Ao)38B%;j4USAJnJZJ@ZTO^T;n)*ElA}P3 zjL2%q*WLg9u>6?IwYa@=I^!0ZCm_(8N=f1mTdm6-A>%1oq;1R=Y!n$1G2te@TN&M? z#M@d|mR$7LBf#Ok&L?N9%X+DDXdj!P@X-9p7&6M}{@Y+R9Hh8rj#GLS<!b-Due^kE z5Il@k9=-C(Y-&esjW^WP!v*EmBm+g~yPCw4z$+}r6$yPRFBH~V-tr=#4eXEyX?Tqs zsNTW7Q>^asOnpcE(v|j{@M819Wnj`_VP|e4QK!r{9)AAge`*`ryWa4gE=I0tM`Xz0 z`Oxt2t%r%1GW7NkZD_7!RqNRONo>xb&+%9n(TWyqTktQE5$niCe!%LhtS*2eyY^Q# z16#GNs+Xkrpmi`C6E#5LvL!$cGa~fmdO@06q7ZAK<_tc5zh#H17nFEg3SOz%qQUTf z(M0Q0JU~DQPGzPz+_yF6L+{Jo-{&edHc0&o;<BE$gN?=;B>@~@#4Ig$BRCS<WEp^+ zK|!^Oh)>%~n<w?8{c<!cqqd&u4Shad-$eJIID&~B#MD@3X)1!y<SyvDgwSD>&db(& zpz{5%Q<>M1oe*92UIli?v>aKZzzMixrPMa-KYg!b3E5aZft3UM;#THNTK#cay^j2( zs(DJi#a_YdkSgZ;%YV=(|8l>vChy+`xE-RQ`F-P?^Kn*#DJV_GFJz)WIHO#w$!i>( zwIt-wL9)u)*uWyf7T!Qt#6m~!IN*FHsLNn@FLQEu$wFJGP=fpLs3C(C223j&geJBy z`-g{z=6@szic3nkvN+tlLjtQ5)lSvrWrJ6V6JrU1q{EyFn`iNiLBs*^4cC#eu}E(J zn2)cV3g%l_r!fs8ZfDrT;)i#?JC@-TgGNiRTlSW=8n^_ci1{cQ#&#(9y|lFnXYASB zJVglEXXj$~L1wXSvTot8*&@d3`F2HY?3_ya<dZ?4oOSuWX6EG?;W4`rJ?||@9Hdq! zy8O9`P<7rNrloie?mL^~Sgh3NT)A!Es&N~E?XwD-(FXFaGsh_(QEE(8a$e3{piBMi zJu!j156TnV;VmUy)DCz#h;t$S=ZyE$8vwy81eHtRfnjey5AbSa*qj<N|GA|g_@3+9 z#?%y@FoVa91d>WFH7_l}WP*i5OTALDuC-N-RRNW4Y|(yG61_iQIVuVb5fNnuNsaWf zzkFoVKv74h?-mCCVQ8oZUe)|tP?@4)^z;aO+Y$E{6=^6J4NNa_4XrOwgmnF!EInI& zcq6GK-|6@Y-&OjF+DKN6(8(A@0&`mF?T@cW^LEG-@t%JnCBjzC=Z_k=<a%sqkq@BR zZOH&+l8pI>IVI^`Ww4HnXe&BgweJnrOR5J^K%j(OQUceDChs4L;?M~-4J8YQ5Rtz3 z<!(-Yg`go-;h&xkH33sx|JJ)>$5DrDVBJSol_C}aXu&65Tb`|DwQSGhjv?9}pEK@Q zvAzop+abfnRIf+585%_`=x2U1%CLWHw4a{wO*S^)@Be(!eWVXj{Rd<w^b-O&TO0@! zIbWX^grGieZv0*fOrONW`j*7{BR4(C)q3ZT00F_$M4S091$DmJ%D5;eAw5BHF<n8- z)U-^CWpKKq=+&mm7CQRI;-qXURb$WOW{_o^R(0V;kguZkK!6KJ4qyp0pBuI{M&BYE zHV+t=xdo;;rE=K?U&v&?5Ux=8KW~V@0R>o2r0-#2!6(+&ZL5X}5G#Y31;VP!Bspbb z+gu|a!s-HiabC^;5<ug@7l^O7`$FL*aHpL9J>hA*=WJ7v<*SeBTUttCY})24otvGV znweXc)+yK6Q{!<<W(mY{fCvg>8(TADU1Jg!_N~!fp?3Jl3x3*bm>VuZH28=2(q~9W zM=x3qNctdns2dWJXg<T#Rc$iv9SQ#Ul$?BQ^2F$`5OhadGz;6wvvw`VW*p}-i9zb> zb-;KY!{}&$zrb~hP)L<)@WpKLv-W&APPHS$KBQl_sg$+-?Y=j2Rp^F}|ClwiT4H>> z$@AS2<}f9UUbg-MGf4u_<itnay5Oq1rKL1I{*FN^i$m@8R-f!!bwhYMh|ZUMcqgbe zcyL6V2`CJ{bAnI(ZM!peHo&v^V<t4KZja;-C#AQ_=EaSa-)u%6s514a;B<(e=%;UI z?1lk)YNOw%h8ta)bBAig0z~mY+A$vp%=R|04gMRpPcQ(ZAdV4yd;+S&6aol%@pjU$ zw6VrEA?9PUZ&_f{wd|_P3*%#vdZ~&n_m7W?4h~qAa1as(oRuOzk1vv1qdV+i9tcUx z>!@*sm|;j0YHE_C4}f=xoWOY#`i^0*G|T>vd4K3!GZ}b$cz7h6EUex-E33_6oMlwv zQ9<48IQig+kgWa!lT&7k8rH}k)HM2AkhIDbjz?~0*3Ms@u+6)xztJZvC$ZZz!@+0? zufMK76HCd<N@c6-c!jXAOlpw^NSwF=;lZ(B>X#d0x4TI1E1H#&GK<M5(H)h7La{<z zW1YB#>io%$=OfdO&iDJ{y4QnWxKiM5pdtSQq^o$7#m#5Xs=+{N!!$NE6{H@u$rzLZ z@oQz=Wq8va0ntEqhKb>O7FLM~VCg`QsM)<-5R6_>)|zm5X!du`EP%CM@vKQ@Cp!|S zp&K_dr5gLM@+T%vBL^Zjlg}q(OM7zg1bIW5!o6MvWuILb2&n!NV&7a{8ScTcXFs20 zj!sZ^`xgGqQ8<!7y>TNO{eg}ijfD;@#zWHDzPP11M&<*;8L8|SO21I)k<J|=fb67# zfl%e+V+HlLA2NPvSiGA`q|bpnZHu2&igg_86WW5YYTVcZhi2%A%ZxRrI-L!$w?Y_k zrL{+q`lYt+4RDnBL$?p0ac?&pSS&SPC<8g6f%`qLtvgZt6*T{7ruN>L8hbz7P0ApA z$&(<YX&J51q*@GSQn(n7SDKWM$jmJ)2q;nH@^H%d8FHaiEHJKD#}&p3&yOPcF725s zT+CwKb|w^~lOGa{-m}~16!O+!&w?VtjnJc0FN7p8K^z1S4nCWt!NGpl$lHpJ*Nz_Y zNsrHzh0lPrT5|PM`l4GETpZTNn@|!Onm=E<IvWVSa9#0S?w^$#Jy_psYHEM)KtT;G zj3HLF92q$d>P0azAz4R(5zu*ImrBGYCYEu2J*8sM)1EmCP0plx&cH!eFMSdOChvHM zo_Nk=mG@)lytD&<^mAGJNuYgLX>Qy4$h{x<(*`IZ88w_7U;S)g|Fc(ufI)gY6XBmY zC{Q<4?M?_W`#X1cE>2LN=QNd&X#4P$w*yxyD&RS~#g%Ln;De)Sf|QNn%nGYZ?J@R` zk0}ZrR~9F~FqBHTeUhj!E5EO7Xh`DW<vsQ^UG{3pTqkMe5Y{5iOvxcCjN|@n|B04i z_5>m-Dyo3HH0aa>8vQ)m#VEHv9y^88-&E4%^E+6WL)DqBzF_iraLDCkY*kd7Wrsy( z%p^3VukW%S+ia)ikH?3Hg>{&@5z6lx1D(D0(fJFV;^0LMr@Nvlfh9S*R5Ix9gD(Uo zz?egb5SOSvS#JH*GAq`$ozvm4kh?dP3wXl&!4-c*wwyJ$={*SDXJ_oN0eZ<K)pwCm znqqK1*_{}XKg+9P-tUg(KsOwjtae@%7VK}Ym8#6XtNMrbq(Hb`YgU~7k1!&d4TP`N z2!asV;q%jUSmtzb4UWnYcYLb@n>`v@K60>20^>mieuJow^mWCx5<LTLUNm{%J|3gu z>cxd$K?#ze3ku9v={TGLIi*2493!($2uuPj1FC3Q+F~vfDJtv(6KV{TbtLw1WMt~} zc62lwWvIaSp$B8$uF^;RbiI8&<CH_Ax%Q(!zUcQwY+rs`<<CDi@o6v29|Zvf6O1GX zq|f#@<3PwIxBC#}?I$i3$q(@}&=DO{duUPKp@snQsqOy66MSfX#$&8}{15B5^*We! zi1oTe?2x2rAJHiZF)?$+7^661mXr*ir*$GCqC8qV3RWRZV^|Ybf4$3>=&$G)vL*S* zo6|SIi~T1q8vLraU0Ogx>>{k5VQ8HAbHJlRanFP#6AB3EF&q84PL%siWgP)`SSGVM zJLKgia<A5_8T+!uV0M_6&G<&;bjoD-54sH+7m-r=TnxhcLOyX;ad|`OoFbp9ua807 zw`P+F#B73i-K*UbiHxmaJeZe<c~6Jgr2NTT!H0M}DB$n&pHr#w+ec5!g#X*g7)lQb z$P=3~qid>8AD8unl3;=Uec94qWoHz)YxMp**9=FSf||<!R8(AQwoEIas55=6V`%Jk zI|Kp?VjPNpC}kUQyt6fn246u!?v9paKYsa{X$l`SrR3hkO;GX``ophAN?#!1@WJDL z?*Fv+-QiTf|NqBv>~(C}DJz-T^H6s7NOsDIM0RAHin2G6JtDg(5;+JVd($x^dxUJ~ zck6R~zMr=~_5J?+yRKaRIOn=}-LLz3KiB;nkEijPmOQtJh_^mRIEx&Z+9B1e9Pyde z-``ggc~tB$ICD}LaJ00L$mL)XaoxaK{atC*G~4VJz)f>Wyh1r2*W}9Wv{otXS-+=m zTu}9>I2r#e^(htSB@Ohy*C8(iasjZ5K8lHn2@Inv&hm<Cr6f@K>ZVdQsCe|_t%v>B z<T0~UGqoPjD$~CLVO5$^>8#Re*AxS6_B1RkD+<1G+&vT$O18u>|5)ev_;|E-@ex(8 zW=1$~7)8|b1?t({{#N#D-M~j%zMK)rL{(|C(!G!13DGmMQL3Kf61Z__mkfO6L`J%L z_Np&kI+GD&rFqtg=9l24DXv1ubkmYFY!oezp;XdC`Y`}P+x=z;UC(~$xOrp;+7Dk8 z=RSX+3IehF+u?P2ViWu8Rpnm)H7)}iwB?{s51eUWrb;NQS7nq491s<JcNO;zG4zOh zedcL37e-~p&2uPv8Nyp!(nYFmYWhh?H3(XId_``~i$b}o5o?m}ys`x`bCKM>1qU@X zq0f*ozv%p97>-UrmfU1@5TS=bG(y>y)4(uJO_y32a1kwh-m2xfjL&ApF&Ou`&5ewV zB-2QjjRyTSvZ)?z59kH0jM8WH<*Mwa?j#HPQaBDj%dO65K09HZnAX*ao>E)b?^xV+ zn|F@Z6_U9843GJc=V&IK-_9hLBwaNfvu5ByNWT(RTs%6nrX`yb534%l6f+WGiT%YJ zmX1BC3)!r`><|l&>PJ~KveU89YJp~Tj%a!-Z+a|#Cw@W#lELcv@m5?uZrbj_xx@a! z*PaB4SSnW;T^g*{Z6va@&+Q&jHCdB9<Ptzd`VXfoeZO4y$ym=s-QAr;U)NM^tnyp; zs*I0>jAskMl2;qDUbVH_fR~4NYH3y4P&bVYB>A9^pnK&y>E%!ES_{Boj8`&1OMgMZ z1*Qtg1ROB#nigx1@6}y2O>t;undfskCytX#eX^kDYl8f7zM9F4;t($9Xr%}`O)Y7^ zI%o_dPXkZs2cKmuG5<H7Ykrb97p(g~Vl)?SfA^Ey-cp~B7%Rzs?!Vcd*4QR<QYf~9 zev>@MD<0X#QxF$R2K`kzpTIUOno+92K(>E=nuWcsO--B<0o~i5=Jg?FtkI4MpzCjJ z_@KqaKYQ^cvnBykIRm)|!6)9z3!7>c78i^N|A?I(6SqOIv0>cxnNEp_=Cg#Pe6M?{ zMP1T3W|C5L{Jzq=0MPvw5+)uqHO2K5D~*a;LiDIk%mM`w-Nmb)ltUSyxZ?><`k#C+ zr?#;vhyoU3f}OWA_STBMh((dgz*LNJvgtCll_q6Km=1F+Yk`1?;D-y3b|S7kClmO* zkVnt(eE0o|t>(lKHA9={9#3g?u<X$t>$))v@UiWh5(^h*$Sl|lQhl<r*tj@-*pI%C zjxE&g$gNzXO*yUfz|v<S4s5H~aByi*r8d>kQ6is;HXV}u2&1@s1-_dWAYQWNfj_^v znl+dpYJdBcHf<tVnQg4y`hs3dUkv-DmA6Gj5)OmH#qC+`iT;XCb(>gu>u*b!Jt&7s ziP*_BL@LxWQ<)%N)5veuiQ9k*_z?pAYu9uO4cVHOlM#M!2y%wt!K-NodI_5kKV-g@ zYnkVUg;mTvsoL5u+oDQbjqC_M$*`UeG8q`X?C+&363xigb&aPkSKWV$$82Iu%&C=w zo1n~o_I+HkRS{Lf<;QEbJ+{Z&wvq=$ee(tB6JNUU8UG8Hk!^dEX8HnP4n}ruFp^7T zAdMXPK>xP%Jt^q8X{SQidmSAeDoV=YZP0c?h>xEU8?;D<n0X>6{rvc7Irh$>g)oY1 zObZNwGaCDrMbuU9E2wx)<xIhZrFN&a+UOmDyJ~R;&f0KAB}HaeIn-|Hd<WJmH_G`% z$(VY)W`Fc2AQ)HGGcq%y=RV6N9v>#=#r2*Q6qG;c%#G7#W(#{zw-@Hn-jyVyArZc_ zB8BLx+YNGY8PQ{Hm3_Ng5xNl5UNT^PxHe)kr;+|H&fI%1^`yBg&3*1=g_JF|zh{K5 zt}H&z=`h5k_em|@kw^fH)$%C<ByZZ@oe!uzmq$W?tY@{fg;H!V(bFpk_Hat#c-<#U zsgt`P6mz`Sf3so>FK^^}0WwkQXsc<f)L*vwwm*95Nu`R%XM7SO7Nb3LTQcgeJKiGe zdfa5>jEo;UStb|`X79sUHU;H*XOV9juLCwhI5-d`u5r)S4VX=^e7pqMu99<oc&4kn z!07`&dB($rn1{@u<Xz}e-^)pq5||#5;wm=yZfwQ#SpJ)eE2$5Nn{u=JN`jdFD`TX| zU7r9yP$Od4<=K2i@Hmt*;1)KBIe>@$;}`H%1`M@vWt|>&6_F83LTGK>w7kL6&iz`# zo}L8uB??8J2id!{?K?u$T0Jp7uH@*r@?}hgZEW@Z4r$`R;ufgLm%}W`dQT#i=bdjv zo0tY>w!XyOnt##wge+CSJZt=X_9Hn4rUxVQk+{&bD;Xb35|WdjORHMXFLJ=r4t8$l zD0J)|uy~~y`qd6r=;vNUJ>2`jqj-zxX+nZwL2+@VHNj^QmC0rcOqieNP&lrwgj3a( zxBl-vVmC$IrZugtsomOQto6;!Zzr1hs68k$-)3%VY96-MP`=2Pj$ZR$KV#<G;TU1W z?C{G)_*opV16RGLSVi&ikp%^6gd_ynAg0z+&58%L;h1b{g`5|uadTP|sNRg2sQSD+ z(by9jSiSO=VL?o6LY0XrRpyDtfw-`u{}Cu;vmzuUW|hNeCtBe3L7z<Cy^LUtyHMDc zpIzJN==P8;O%XLQ5vdf}=Ju|aOvd?rg672RLnH107F!YBT<XNQmuw+p?XSFg7`>0> zA{~+<^bJI%d}vi~y?_7qo5h2^yUiG8B`|(j*yanH_r@Nl_}K9DPfhN*dPewpyT)e| zXXb(aer`^dU#okZWwGLZmX_i}J=nX4`w^g#I>?@3)Bti37s|)xJeZ_jRpJ;G>LKSb zmXU!le!Kjng;{v2@Z-m`RCILtCf^qeTnH`kAi=xJ*jQQ|tVyb%1n0)#&e!KC5;uM> zE`5d2urOio>5YT<s3!WeC#|v~eT+i3d*4f$Uh~l$rJ)Aub_L_9o$|!Y4-$KuF)!w9 zBzK-%^W_&$JHzHYYarGWE{1lrizvry0iO7{S>XaG4wLY4SjIaoml>>BhgPMNibxe! z%Q%Fx@)H}csN_a)#p8wrk@T^=TqWknR;rS<*NsdYPl>TmqkY<^U}VIls0142qwR`q zBj{e*5;$H}_IW?|Ajb!a`!L`+MSfv%CYawc7@-FN8aJ5WL9X`bQ9GYZ`uKyR+kHI` z){jjj2t5mgT>Q5-XxlzbYd#EPx}@-4u3i20NfF?=R@_{dr8z2*lgl*#qcNb-yFX&? zzlohJv_fpJpE9G)FRQ9`baZ3(zQXB(AP80qg*K;L=FRPoi>#C6u!6$EDo{|Xs9b20 z-F=P^7UxEYeEireZ#mmDRz8@3ikVp{H8r)rNv^`f(;bwPB_^a^2F=4SWc+qgx)|Tk zGE4BwF?+^V9zH!pleL<E?5cAei2X)!+yASuocE>!zmsgUtv7R>)C)(Ob^i~`RB+nF z3?D<)VEX8+YMf>SyzCOz{nBfO2@Y$nQvBhw2oyUEp!kps3=HU9c}$<13#uM8tSmtW z5O1N5zjlR!!&_{7b2FE0+z0tWGbzI}q_M@?dbayT#~9OxNX|O|#Y$Cd!cD|%FV@;L zsI5!?LTL7G%KdM>^@oiwVoVHfkkQigm4#g&J@B0iYb^*-r8V=S0ri8A+Fzz9Z*P;d zwGq_+;<PcIcq9=wL*wPayPYQr$T=Gk9)8Zk!u1F-OJO<OUjYLE{@l^ws|6LWzZ3Gl zHqTn>7^a|%B@Q;zCkDWsD1qT(e3iY_pndPkUV^rO0Jzuc-q6C_#Gx)Xo&Vk@`uq`2 z$(rv@ZKSq|$$O#i!Bdz>|EkauFr(i3)*|^=PfyItZ`{o86e{W(FBFNsbvFc-+pVT7 zP|?$8xxN7DYGdQu&CBKaIXPD~urw~ji?61+j>m5;EtO=w_xF!|ZG8UxN1gF;r-fb? zOvr~rm+;pv3IhL7!zU`a<)m!%W|frz+?g9|PY0ynQWO*vB-kVxa$j4z!kwv*Uuurj zBp@Kk<QZ3>d0mYAcK)iby~OOh+;^%wUc@jg&$F!l7VKz$<tLK3DxNopWcpdxzttVa zhL6y`I(NH*9=aVfop+7z+`=?u9o$!YEz%Fgq-qm(=%-ThthO)&m-aiHN?ueMiIm^1 z{ju*;abNwdYk;^{qJ@P&_0e*Hy5ne5dg`TfYz=W*15U9qEgF10g&FUNI)`3+GkOy8 zuUwg2(~{A$C^o&^F6U$B3Vqx6+QVXQ``WQ;Y3+tAdh5B*@&{3xUy%N^6M-J?uN93V zhTY-l?(bLOO|Us87em(gerP{;ceB6<0t4Gv$m6kV`x?AFPqFNRyhuajd)Vrd*nXoJ z5+itCKtN?@E5<4(dVquo8y$pD4-K@pFF-4?a6zHI<Z#ZP00rjv7uI}J4X2;wSgzf} zohP?zAH1_a2@<i5kqLVDUL9qn0%))b;n8m?wT}~yC#gb0bSGXJ8hsLROQdO=*v!dZ z;9SQYDyW-!@qSwirBX<+{N+ug?vsuT{yMKv;E3PdmW)XA8e#v|)3A3*BrmF2Nqj>x zS#0oh(3u+K*ARh)kTVDr5+?Z$_x|<!1bJn|*<}JE_SKTwW*1lFVb#0iev9dt%!%;_ zGJ93s^@_1GFEP)mNq3`i^wFN0K!q9FT-kwv^Nyv2Ke970I7zl9nNmI_gYM&B#8^?I zT_-F~68HmR@<<&$j!4@))W%WUmoImE7A=Q{#B`a48fmbNECb{M1KW3I;DlsS-{+Sc zR{fb1uj%)^`-ag+@<7Q=6(I}bsahXuYah+=AD%_~ukpIAh+Gr5fTT*1GD|-t{aTV8 z%D>0%TWg=%d7bVTfICY=C_aJcQv9PYtd>y-fJn-)qLyEt-8gxb7!S*xK;OWiuaQhn zNq4578eo})Gat{)=<8gc4Ov-vZL95!uc*AFb>l%*8H(?~iX1M0jkMu&*D*FGo~b*- zM{}!!2bq_CKPl~KhsVRLFFq8EyzI%4--t^}(ggLhlag!Yw+D+}3Ioqe?M!lx;*aO( z-8zRIS$eS>uMFAh<BMKZI^aJj_m*Mj&`>D$9GV>Rs0D5F3x`C0V0ccxi_cQH?R<~2 zHYsA(0XA|<5uuntILDGK#0VR9RUza3`_ML?wy1{T^Fu^di|2rOy|OdDqrAUd&cCfu z)|U@@Y!p2wHU&h4g-35I4qc2*NwK$^VH1bYO$XM`od;=k)!ErxQ>k}@DTD}nco{Zw zVqy~??e~pkxr`#gSs2+RYoSU+Ymr|w)ziZ$eeY;-(KuPwmD|i~W1xRzWFZ(ou6J+j z&2u}WxjTG{x&?8jEkv$Ov$VYl;psZ~Qp&&Ly;O0YWGlb92O6>puwuQuX{xJx)v;K` zR+^P7MVJ~HZ&CVUY^^F16cE#r9$_7pch&X(*jp@gy4sY-f5X@J2+WB4`ayI1eo;}; z<8zr~2hvX-u}<>A78w>nS0q&smFK&R?nVwMf6Xojugp?QKayBi^qyP)tzcoA#x?3| z<Ma8vWhGg#uLr{ha&<{c5lLDgavh?!kYuGA938Be&^@;Hph!62>(_cWRwo%ymaB1F z;_R<keRtSrv#;Hfse(jc%D_34NO&R7r-`ogteexH+KG%1C>i`B<85BmM7O$7+OE8j z@)xm@k&y#!s=@>NB+n&s7cbb`+rRZ@qUL;&lXHfmFk><xbAyf;YQxqI8bS=>srz%i z7R@gS1{ST#TW%)Yp-+)cGWXt4l>|TmtC?{OcCSE|vt-tnBqjdKq%pltCYa@X;$&Cc zxS0@rn{EjT9Xi_QJBe6rrQ5Q&*RSrs-I`{>8b7G}Hvf*+JWpzEKl_6!-7mKeOG0q# z5NNV~7{xj%4s~2{G@Yn=%ErbvVo5(;6<#KUFP?;OEf17E-gPbBxl`*k#T_Te21ZXm z<Yq-hLa`59yCxDx$0YOPFIiPoye*HOXn0vy__F#1(y-KA-t2C&<^V{V#SrIUN(%}y zUNi?W$9ci9D%rHn^uWNh;=8$&aadSBlu=xp6&0CVQ$GCK3JNK;i7noe1j}Qd0i6;U zwV3`jfNeMl5{#mU7RmtZBrUsw!ES#_x&8L?<E9FmfdddND=AWvJ6Om)>EPjGcfq=T zk@q*IeCq@f#?O$B0D4ygvB(I3`gDkGvDY^@T^-CaQ@&9Qr@RTQuH8n1%Z9nIutfOx z&CM?qM&G-IDL5guEATALc2<KpB{`Uil>w|dr7E$GJn9V$sH7`19BB$Sm27+8uSqNG z=#ZCCe|qFG0g}^Z&CwI!p1_>*#<uW6(C~?n)gHD<rI9pz9ZgIGkg56aw&s?!`mzGc z;|Dl+MUuYnI9cLlr}qYtn8e3ZKKvy*GJh@uG~)R#-Jk-)*n$aEn0mmd_2PC{VYssx zbbEPT*TkgQq&TkM?fcuz2LY?$Dbm`+n3pdb-PS;}d*c^-x5yR*TssvNy)4!wa9rq@ z$(sHe=CL}ed`_vWZ!xme?EUrY5@>k=)eafEPgf+ZTZQN_=&6TkSDt{fM(_QkL@p6u z+}s?kCmWdaHJ{zQM{<X{nLK5SDn98_OlI#`fE3Vs#s8KZR4b@soBSFk0EJ0M1RSpG z8yjDZp#}}DU&2xK*!$=9!|B^P8q~rtN?DjqvPD}P8r-P9O9XE2?mG7s&lngO!Wq%h zo6G@&KiFAs&jYaL3n5yJTGuRG84L{SuYYEKe9gB!jpM4U#>@rxceCY09livN;@YT% zqtc<0ov2K``LqM(T$|7)U+N#09clg>B*_xr?%3<pEO(34)jS+5-iv}_V@vPa%e$ZQ zi~co(>tJ8r8}7`71X#`&xVfiUxYn`bF3aD%mq!sr3;`1Yt9KaNUViuWMdw*XL`L$H zXs8Yq`)g=WtAcAwIc3yE8f$Cz{*j&=9tNy(_*|-!M`W_uIyY(Uls@y6)I<{!smI0X zDQ12|VSrm?KTG{FX*$dL+NS5a5Vd09RS(uO-vhqtAJtNJ&fjmX9I@d}@f$w4`6T|; z<1?Yp8loW(jt$i-^7{Bs8<iK!&Qv&#Y34RDiC#3|AvnQ#$(?=d{7WmiFQqd}sM5s# z6iBlLFyZ$DRPCOISAzGx&L{<GOJ&qkaIiZ&V`M`j(sI?kRRfd2R3*@ivp`?EpRu(? zOp&_v78}oHo3u$B4nlF_<!7_QV-j%{-U<G+7`?eTI5@rhejaDcb_&x$FC+joD7FB_ z-yY#zMEoCACrZ#c{%lIg5eU#f2mC0)pKeh16kA^_8ItKTBE>J^a8kE=CBdQxblo-! zJ|Dhe&`S3M;CpmWq<g0^KbR+wDtgL($}mD;DT*ghuWaGI2-H`YcQ40*%a-%iI~S#3 zyU$F|JzZ=4X(kG?Qmm$@-EXL<(W@yw*_2>%C@<M4ASEOwe3A2&3Ox-PA+%-Gkn?ka zVA!*rqvO;amVt}<mBtU{>EY`F04|j1XoaQAp;p=b9!z{ErEj5us59%f9w(j4)uro= z7bD%>x3^Y((t8U_>y$@ER;RAo(fsI)(o@S@8I4zeUU?VHD}Q}^puk;Uhuhz$8!`D6 zcG7}WG2K3})vC-N9T{1T`Eb1Leyt})kG7jzosZ+5rNS=}6Yca9cePF_3J!|{He;lo zJ5If|t1I2g%4!$SM4v)u5h_oIhPiD1nD>B0DL%1{03F)T-AhZSQJ+8S1bu94N8hxQ z#(fk(2m=}R3LzFWIzOqnVLO1BwVM_sbtJtv>YQ%Z?(Biy%Dxd>-pt@bagWa`or9Dk z2NkcoOiaeOY`-zLO~;Loy`AkIb$_k{l^-c|zak)LWqgrlm3Mh^BunN;&0Tx@ISS%g zw_WE~G;jDL0|T1`mU;X%IxdV47BR)835FW_?UCl@kr)_;lb;LHsYiypH7Cijao<G# z;>l%*VwG0O&%kMNe~3JEW6cmoLNJh!5E^C35qDF(A%4SsDr8ugP7vF4d8O0Y;1IE! zpxG@K^i?m?)RwJBjm61y7YpMiCnJ=7@C*#DMcpcr2NZR-IGK2!?24+ockWHg$B$kB zO((Z(U7L_>MtKzr>sS;U0O;g`tDMJ!;+&XXq0x7)={8>`qRW*p(Tvq#(VU85{U@G< zcTz9;2xWC0zAg*}^Xp89L`M7igFbL@vbytr>y%RTY|~KX{_tb0RO97#(FhT@fPi-5 zvK7Ltc3*vQak*cF`4IvY50l)JrEX!of902>KfS0HXTTS9njap*A6`a@OrRmkYr8n@ zJ>~9UOx_+4FhlS((+6{0TP+3xqd8kQlB!z@g#=_|E>~_?+!{}>q;2*$;A8$epBPZ% z&vT*eWlarLGscg53U(?fb*kJf;3qI$p4q*5A}A@iDSgS8fc6g#ihFThB!m7qtNroi zD#PNoR7p-wj-IyjQ(sZfh70ob^>HzhS9dhS!?#Vpy+!=ICfZU)sbIc`2x+#PDKIgu zbdED0{9@uxuiFcp-i)nTq%*6fIgr8fIeg$aD5BBmIRjXX4-AQZ??Kn=y8MhFsQJCi z`g~9GEwpu1Adh?Fc$#8HcI~6^<6LF7V<|~#_4{^2r^7msQ(q;4g+g$05d*rHMIap1 ziQ*Gz^bD+V++C|}gyGuJ0k=xT^_>xwc3|!Yz~VRE@w!G5_Xz`VrO{(7l5SDS^b9|Z zt1~Y0?OV}fDP0BXcx%vuu@J`l3h&Q^h2TF+IEe-NEU=2>KMO^eNHI8zo4MlTIR;_1 zm=1O7<)G{QS>99_xfMQdBZW-kXV?>wkYoc*jGhiI?>w%l{RuiCo{Vr<@+7@wu#6Za z!4p#6Y~KGx?f>)Z>dBP!)q6~tIQY+k5O{fxtEy9Bqa82a-C;gw=kdeva&-iYToQnK zCGNP_X~|D7<`<G#9JYAZ?jA8N7B(#T`SXalsFz9vXRwC_{tUnkl(aBZ_G~7>4ie{t z0OHRPo}OaC(Rr_4ML&2@3l!JH2%DuG9Dx5y<<Tdq%;e`kqwL&vM-2@nDv0-f07$c? zeSA`)Hp^E+o<8lb#nfZJYg@=L@gjC3f*x`rLFo$spGZFcorUDr>WEYJ0VN6j1hHfi z`wY4d%NUS%3kr(|vSb__3P*PBD+6D_@r@KSSTPU=HV5~va8N=2HS>0Li<GzJ_iiv+ zfhEW1`To9fTh~OXk2Hwf$pDaE4_%4GAZ}h>HUJ8nrhb$6l+SQlP~qz;z`I`m)J~c! zkI;b9geqQw8k7lwsmYf$&Yq1|h7YH`Y3-H~f3S<+Ne^Ff5hah-5q_|%f_8E9aPNIv z)baClheJ`(T?bYLlgnpPP3dv}kL}8y+!I+MjKFvmR0IHQrPDX(BhPH=@3ne0(`G~n z+aedYqMP{HIsia!mE`5?gXV@^oh>clV74K;J4T6#iI_K{p0yhfDcLEmqpN#GS?B}n ztUAk6=U*VT{?R-GD1L`+l9D3XIbDOtQt0P-M+JyOghfT8!~t*+ZWNdShV9wd%epQD zdS?w6?VR$SJ*!$HBi;QRN`Xg~35uS9w1`Zq_@n~}<IJS;xmf8%$NTSmhI?M<uQ`Wd zV-*s(Rd{M!yW<Q1w_U0(?<9@=zx*;Pqj>Iii$AuIh~PH_=_L?o<mY$Ne8a4Wg@yDm zKhusxOu&SMlyr1m)FwC̆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 diff --git a/docs/intro/README.md b/docs/intro/README.md new file mode 100644 index 000000000000..83dcc31c56ee --- /dev/null +++ b/docs/intro/README.md @@ -0,0 +1,43 @@ +# SDK Intro + +The [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk) is a framework for building multi-asset Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as Proof-Of-Authority (PoA) 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). + +It is based on two major principles: + +- **Composability:** Anyone can create a module for the Cosmos-SDK, and integrating the already-built modules is as simple as importing them into your blockchain application. + +- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. 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-cababilities. 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. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each third party module. For a deeper look at capabilities, jump to [this section](./capabilities.md). + +## Learn more about the SDK + +- [SDK application architecture](./design.md) +- [SDK security paradigm: ocap](./ocap.md) + +## Creating a new SDK project + +To create a new project, you can either: + +- Fork [this repo](https://github.com/cosmos/sdk-application-tutorial/). Do not forget to remove the `nameservice` module from the various files if you don't need it. +- Copy the `docs/examples/basecoin` directory. +- Use community tools! More info to come. + +## SDK Directory Structure + +The SDK is laid out in the following directories: + +- `baseapp`: Defines the template for a basic [ABCI](https://github.com/tendermint/tendermint/tree/master/abci) application so that your Cosmos-SDK application can communicate with the underlying Tendermint node. +- `client`: CLI and REST server tooling for interacting with SDK application. +- `examples`: Examples of how to build working standalone applications. +- `server`: The full node server for running an SDK application on top of + Tendermint. +- `store`: The database of the SDK - a Merkle multistore supporting multiple types of underling Merkle key-value stores. +- `types`: Common types in SDK applications. +- `x`: Extensions to the core, where all messages and handlers are defined. + +## Languages + +The Cosmos-SDK is currently written in [Golang](https://golang.org/), though the +framework could be implemented similarly in other languages. +Contact us for information about funding an implementation in another language. diff --git a/docs/intro/ocap.md b/docs/intro/ocap.md new file mode 100644 index 000000000000..7d57d0c34e2b --- /dev/null +++ b/docs/intro/ocap.md @@ -0,0 +1,102 @@ +# Object-Capability Model + +## Intro + +When thinking about security, it is good to start with a specific threat +model. Our threat model is the following: + +> 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. + +The Cosmos SDK is designed to address this threat by being the +foundation of an object capability system. + +> The structural properties of object capability systems favor +> modularity in code design and ensure reliable encapsulation in +> code implementation. +> +> These structural properties facilitate the analysis of some +> security properties of an object-capability program or operating +> system. Some of these — in particular, information flow properties +> — can be analyzed at the level of object references and +> connectivity, independent of any knowledge or analysis of the code +> that determines the behavior of the objects. +> +> As a consequence, these security properties can be established +> and maintained in the presence of new objects that contain unknown +> and possibly malicious code. +> +> These structural properties stem from the two rules governing +> access to existing objects: +> +> 1. An object A can send a message to B only if object A holds a +> reference to B. +> 2. An object A can obtain a reference to C only +> if object A receives a message containing a reference to C. As a +> consequence of these two rules, an object can obtain a reference +> to another object only through a preexisting chain of references. +> In short, "Only connectivity begets connectivity." + +For an introduction to object-capabilities, see [this article](http://habitatchronicles.com/2017/05/what-are-capabilities/). + +Strictly speaking, Golang does not implement object capabilities +completely, because of several issues: + +- pervasive ability to import primitive modules (e.g. "unsafe", "os") +- pervasive ability to [override module vars](https://github.com/golang/go/issues/23161) +- data-race vulnerability where 2+ goroutines can create illegal interface values + +The first is easy to catch by auditing imports and using a proper +dependency version control system like Dep. The second and third are +unfortunate but it can be audited with some cost. + +Perhaps [Go2 will implement the object capability +model](https://github.com/golang/go/issues/23157). + +## Ocaps in practice + +The idea is to only reveal what is necessary to get the work done. + +For example, the following code snippet violates the object capabilities +principle: + +```go +type AppAccount struct {...} +var account := &AppAccount{ + Address: pub.Address(), + Coins: sdk.Coins{{"ATM", 100}}, +} +var sumValue := externalModule.ComputeSumValue(account) +``` + +The method `ComputeSumValue` implies a pure function, yet the implied +capability of accepting a pointer value is the capability to modify that +value. The preferred method signature should take a copy instead. + +```go +var sumValue := externalModule.ComputeSumValue(*account) +``` + +In the Cosmos SDK, you can see the application of this principle in the +[basecoin examples folder](../examples/basecoin). + +```go +// File: cosmos-sdk/docs/examples/basecoin/app/init_handlers.go +package app + +import ( + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/sketchy" +) + +func (app *BasecoinApp) initRouterHandlers() { + + // All handlers must be added here. + // The order matters. + app.router.AddRoute("bank", bank.NewHandler(app.accountKeeper)) + app.router.AddRoute("sketchy", sketchy.NewHandler()) +} +``` + +In the Basecoin example, the sketchy handler isn't provided an account +mapper, which does provide the bank handler with the capability (in +conjunction with the context of a transaction run). diff --git a/docs/intro/sdk-app-architecture.md b/docs/intro/sdk-app-architecture.md new file mode 100644 index 000000000000..4b302bd33439 --- /dev/null +++ b/docs/intro/sdk-app-architecture.md @@ -0,0 +1,62 @@ +# SDK Application Architecture + +## Parts of a SDK blockchain + +A blockchain application is just a [replicated deterministic state machine](https://en.wikipedia.org/wiki/State_machine_replication). As a developer, you just have to define the state machine (i.e. what the state, a starting state and messages that trigger state transitions), and [*Tendermint*](https://tendermint.com/docs/introduction/introduction.html) will handle replication over the network for you. + +>Tendermint is an application-agnostic engine that is responsible for handling the *networking* and *consensus* layers of your blockchain. In practice, this means that Tendermint is reponsible for propagating and ordering transaction bytes. Tendermint Core relies on an eponymous Byzantine-Fault-Tolerant (BFT) algorithm to reach consensus on the order of transactions. For more on Tendermint, click [here](https://tendermint.com/docs/introduction/introduction.html). + +Tendermint passes transactions from the network to the application through an interface called the [ABCI](https://github.com/tendermint/tendermint/tree/master/abci. If you look at the architecture of the blockchain node you are building, it looks like the following: + +``` ++---------------------+ +| | +| Application | +| | ++--------+---+--------+ + ^ | + | | ABCI + | v ++--------+---+--------+ +| | +| | +| Tendermint | +| | +| | ++---------------------+ +``` + +Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of [baseapp](#baseapp). + +## BaseApp + +Implements an ABCI App using a [MultiStore](../reference/store) for persistence and a Router to handle transactions. +The goal is to provide a secure interface between the store and the extensible state machine while defining as little about that state machine as possible (staying true to the ABCI). + +For more on `baseapp`, please go to the [baseapp reference](../reference/baseapp.md). + +## Modules + +The power of the SDK lies in its modularity. SDK blockchains are built out of customizable and interoperable modules. These modules are contained in the `x/` folder. + +In addition to the already existing modules in `x/`, that anyone can use in their app, the SDK lets you build your own custom modules. In other words, building a SDK blockchain consists in importing some modules and building others (the ones you need that do not exist yet!). + +Some core modules include: + +- `x/auth`: Used to manage accounts and signatures. +- `x/bank`: Used to enable tokens and token transfers. +- `x/staking` + `x/slashing`: Used to build Proof-Of-Stake blockchains. + +## Basecoin + +Basecoin is the first complete application in the stack. Complete applications require extensions to the core modules of the SDK to actually implement handler functionality. + +Basecoin implements a `BaseApp` state machine using the `x/auth` and `x/bank` modules, which define how transaction signers are authenticated and how coins are transferred. It should also use `x/ibc` and probably a simple staking extension. + +Basecoin and the native `x/` extensions use go-amino for all serialization needs, including for transactions and accounts. + +## SDK tutorial + +If you want to learn more about how to build an SDK application and get a deepeer understanding of the concepts presented above in the process, please check out the [SDK Application Tutorial](https://github.com/cosmos/sdk-application-tutorial). + + diff --git a/docs/introduction/cosmos-hub.md b/docs/introduction/cosmos-hub.md deleted file mode 100644 index 0e40b7b4c199..000000000000 --- a/docs/introduction/cosmos-hub.md +++ /dev/null @@ -1,32 +0,0 @@ -# The Cosmos Hub -The first blockchain in the Cosmos network is the Cosmos hub. The Cosmos hub connects to zones via the novel [IBC](/specs/ibc.md) (inter-blockchain communication) protocol and keeps a record of the total number of tokens in each zone. Because all inter-zone transfers go through the Cosmos Hub, you can send tokens from one zone to another, quickly and securely, without the need for a liquid exchange or trusted third party between zones. - -The Cosmos Hub can connect to many different kinds of zones - public or private - as long as each zone speaks IBC. Tendermint-based Zones are natively compatible with IBC, but any fast-finality consensus algorithm can be used as a replacement. Cosmos can thus support a wide variety of currencies and scripting languages like those found in Bitcoin, Ethereum, ZeroCash, CryptoNote, and more. Atom's are the native token of the Cosmos Hub. It is a license for holders to stake and participate in governance. - -## Proof-of-Stake -Blockchain networks are secured by a set of validators, who are responsible for committing new blocks in the blockchain. In Proof-Of-Work systems such as Bitcoin, validators are called miners, and the probability of a given miner to produce the next block is proportional to its computing power. In contrast, the Cosmos Hub is a public Proof-of-Stake blockchain. Proof-of-Stake is a category of consensus algorithm that relies on validators’ economic stake in the network. - -## Atoms -In the case of the Cosmos Hub, the frequency at which a validator is selected to produce the next block is proportional to the number of Atoms locked up (i.e. bonded, or staked). - -These Atoms can be locked up by validators themselves, or delegated to them by Atom holders that do not want or cannot run validator operations, called delegators. The sum of a validator’s self-bonded and delegated Atoms is called its stake. The Atom is the only staking token of the Cosmos Hub. In return for locking up their Atoms, delegators earn block provisions (in Atoms), block rewards (in Photons) and transaction fees (in whitelisted fee tokens). When a bonded Atom holder wants to retrieve its deposit, it must wait for a 3 week unbonding period. - -## Photons -Atoms are designed to be bonded on the Hub. This means that they are not ideal to pay fees or to move on other Zones of the Cosmos Ecosystem. This is why Photons will be introduced. Photon is a fee token with much greater liquidity and velocity than Atom. It is the second whitelisted fee token on the Hub after Atom and can move on all the Zones that are connected to the Hub. - -## Hard spoon -A hard spoon occurs when a new cryptocurrency is minted by replicating the account balances of an existing cryptocurrency. In our case, we are hard spooning Ethereum by taking the account balances of existing Ethereum holders and mirroring those values. This means that ETH holders will have their coins replicated in this EVM zone and will be redeemable as fee tokens–Photons–within Ethermint. - -After launch, Atom holders will be able to vote on the hard spoon, specifically: - -- Whether the hard spoon should happen or not -- When the snapshot will occur -- How Photons are distributed (what goes to Ethereum holders, what goes to Atom holders and Photon inflation) - -## Validators -Validators of the Cosmos Hub are responsible for creating new blocks of transactions that are added to the blockchain. Running a validator is non-trivial. It requires technical knowledge and hardware investment. Additionally, due to the way that Tendermint—the underlying consensus engine on which the Cosmos Hub is built—works, the number of validators must be limited. Initially, this limit is fixed to 100. This means that only the top 100 addresses with the most stake that declared their intention to become validator will be validators. As a result, most Atom holders will not be validators. Instead, they will become delegators, thereby participating in deciding who among the validator candidates actually become validators. - -If you are interested in becoming a validator: learn more about validators [here](/validators/overview.md). - -## Delegators -People that cannot, or do not want to run validator operations, can still participate in the staking process as delegators. Indeed, validators are not chosen based on their own stake but based on their total stake, which is the sum of their own stake and of the stake that is delegated to them. If you are interested in staking your atoms to a Validator to earn revenue, or just want to learn more about delegators, read the [Delegator FAQ](/resources/delegator-faq.md). diff --git a/docs/introduction/tendermint-cosmos.md b/docs/introduction/tendermint-cosmos.md deleted file mode 100644 index f7aeb7746ca4..000000000000 --- a/docs/introduction/tendermint-cosmos.md +++ /dev/null @@ -1,27 +0,0 @@ -# Tendermint and Cosmos - -Blockchains can be divided into three conceptual layers: - -- **Networking:** Responsible for propagating transactions. -- **Consensus:** Enables validator nodes to agree on the next set of transactions to process (i.e. add blocks of transactions to the blockchain). -- **Application:** Responsible for updating the state given a set of transactions, i.e. processing transactions. - -The *networking* layer makes sure that each node receives transactions. The *consensus* layer makes sure that each node agrees on the same transactions to modify their local state. As for the *application* layer, it processes transactions. Given a transaction and a state, the application will return a new state. In Bitcoin for example, the application state is a ledger or list of balances for each account (in reality, it's a list of UTXO, short for Unspent Transaction Output, but let's call them balances for the sake of simplicity), and the transactions modify the application's state by changing these list of balances. In the case of Ethereum, the application is a virtual machine. Each transaction goes through this virtual machine and modifies the application state according to the the smart contract that is called within it. - -Before Tendermint, building a blockchain required building all three layers from the ground up. It was such a tedious task that most developers preferred to fork or replicate the Bitcoin codebase, but were constrainted by the limitations of Bitcoin's protocol. The Ethereum Virtual Machine (EVM) was designed to solve this problem and simplify decentralized application development by allowing customizable logic to be executed through smart contracts. But it did not resolve the limitations (interoperability, scalability and customization) of blockchains themselves. Go-Ethereum remains a very monolithic tech stack that is difficult to hard-fork much like Bitcoin's codebase. - -Tendermint was designed to address these issues and provide developers with an laternative. The goal of Tendermint is to provide the *networking* and *consensus* layers of a blockchain as a generic engine to power any application developers want to build. With Tendermint, developers only have to focus on the *application* layer, thereby saving hundreds of hours of work and costly development set-ups. For reference, Tendermint also designates the name of the byzantine fault tolerant consensus algorithm used within the Tendermint Core engine. - -Tendermint connects the blockchain engine, Tendermint Core (*networking* and *consensus* layers), to the *application* layer via a socket protocol called the [ABCI](https://github.com/tendermint/abci), short for Application-BlockChain Interface. Developers only have to implement a few messages to build an ABCI-enabled application that runs on top of the Tendermint Core engine. ABCI is language agnostic, meaning that developers can build the *application* part of their blockchain in any programming language. Building on top of the Tendermint Core engine also provides the following benefits: - -- **Public or private blockchain capable.** Developers can deploy any blockchain application, permissioned (private) and permissionless (public), on top of Tendermint Core. -- **Performance.** Tendermint Core is a state-of-the-art blockchain consensus engine able to handle large number of transactions in short timespan. A block time on Tendermint Core can be as low as one second and can process thousands of transactions in that time period. -- **Instant finality.** A property of the Tendermint consensus algorithm is instant finality, meaning that forks are never created, as long as less than a third of the validators are malicious (byzantine). Users can be sure their transactions are finalized as soon as a block is created. -- **Security.** Tendermint Core's consensus is not only fault tolerant, it’s optimally Byzantine fault-tolerant (BFT), with accountability. If the blockchain forks, there is a way to determine liability. -- **Light-client support**. Tendermint provides built-in light-clients. - -But most importantly, Tendermint is natively compatible with the [Inter-Blockchain Communication Protocol](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/ibc) (IBC). This means that any Tendermint-based blockchain, whether public or private, can be natively connected to the Cosmos ecosystem and securely exchange tokens with other blockchains in the ecosystem. Note that benefiting from interoperability via IBC and Cosmos preserves the sovereignty of your Tendermint chain. Non-Tendermint chains can also be connected to Cosmos via IBC adapters or Peg-Zones, but this is out of scope for this document. - -For a more detailed overview of the Cosmos ecosystem, you can read [this article](https://blog.cosmos.network/understanding-the-value-proposition-of-cosmos-ecaef63350d). - -For more on Tendermint, go [here](tendermint.md) \ No newline at end of file diff --git a/docs/introduction/tendermint.md b/docs/introduction/tendermint.md deleted file mode 100644 index 4192a03ea6e7..000000000000 --- a/docs/introduction/tendermint.md +++ /dev/null @@ -1,47 +0,0 @@ -# Tendermint - -Tendermint is software for securely and consistently replicating an application on many machines. By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state. Secure and consistent replication is a fundamental problem in distributed systems; it plays a critical role in the fault tolerance of a broad range of applications, from currencies, to elections, to infrastructure orchestration, and beyond. - -Tendermint is designed to be easy-to-use, simple-to-understand, highly performant, and useful for a wide variety of distributed applications. - -## Byzantine Fault Tolerance - -The ability to tolerate machines failing in arbitrary ways, including becoming malicious, is known as Byzantine fault tolerance (BFT). The theory of BFT is decades old, but software implementations have only became popular recently, due largely to the success of “blockchain technology” like Bitcoin and Ethereum. Blockchain technology is just a re-formalization of BFT in a more modern setting, with emphasis on peer-to-peer networking and cryptographic authentication. The name derives from the way transactions are batched in blocks, where each block contains a cryptographic hash of the previous one, forming a chain. In practice, the blockchain data structure actually optimizes BFT design. - -## Application Blockchain Interface - -Tendermint consists of two chief technical components: a blockchain consensus engine and a generic application interface. The consensus engine, called Tendermint Core, ensures that the same transactions are recorded on every machine in the same order. The application interface, called the Application Blockchain Interface (ABCI), enables the transactions to be processed in any programming language. Unlike other blockchain and consensus solutions developers can use Tendermint for BFT state machine replication in any programming language or development environment. Visit the [Tendermint docs](https://tendermint.com/docs/introduction/introduction.html#abci-overview) for a deep dive into the ABCI. - -## Understanding the roles of the different layers - -It is important to have a good understanding of the respective responsibilities of both the *Application* and the *Consensus Engine*. - -Responsibilities of the *Consensus Engine*: -- Propagate transactions -- Agree on the order of valid transactions - -Reponsibilities of the *Application*: -- Generate Transactions -- Check if transactions are valid -- Process Transactions (includes state changes) - -It is worth underlining that the *Consensus Engine* has knowledge of a given validator set for each block, but that it is the responsiblity of the *Application* to trigger validator set changes. This is the reason why it is possible to build both **public and private chains** with the Cosmos-SDK and Tendermint. A chain will be public or private depending on the rules, defined at application level, that governs a validator's set changes. - -The ABCI establishes the connection between the *Consensus Engine* and the *Application*. Essentially, it boils down to two messages: - -- `CheckTx`: Ask the application if the transaction is valid. When a validator's node receives a transaction, it will run `CheckTx` on it. If the transaction is valid, it is added to the mempool. -- `DeliverTx`: Ask the application to process the transaction and update the state. - -Let us give a high-level overview of how the *Consensus Engine* and the *Application* interract with each other. - -- At all times, when the consensus engine (Tendermint Core) of a validator node receives a transaction, it passes it to the application via `CheckTx` to check its validity. If it is valid, the transaction is added to the mempool. -- Let us say we are at block N. There is a validator set V. A proposer of the next block is selected from V by the *Consensus Engine*. The proposer gathers valid transaction from its mempool to form a new block. Then, the block is gossiped to other validators to be signed/commited. The block becomes block N+1 once 2/3+ of V have signed a *precommit* on it (For a more detailed explanation of the consensus algorithm, click [here](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm)). -- When block N+1 is signed by 2/3+ of V, it is gossipped to full-nodes. When full-nodes receive the block, they confirm its validity. A block is valid if it it holds valid signatures from more than 2/3 of V and if all the transactions in the block are valid. To check the validity of transactions, the *Consensus Engine* transfers them to the application via `DeliverTx`. After each transaction, `DeliverTx` returns a new state if the transaction was valid. At the end of the block, a final state is committed. Of course, this means that the order of transaction within a block matters. - -## Application frameworks - -Even if Tendermint makes it easy for developers to build their own blockchain by enabling them to focus on the *Application* layer of their blockchain, building an *Application* can be a challenging task in itself. This is why *Application Frameworks* exist. They provide developers with a secure and features-heavy environment to develop Tendermint-based applications. Here are some examples of *Application Frameworks* : - -- The [Cosmos SDK](/sdk/overview.md) is an ABCI framework written in Go. -- [Lotion JS](/lotion/overview.md) is an ABCI framework written in JavaScript. - diff --git a/docs/introduction/what-is-cosmos.md b/docs/introduction/what-is-cosmos.md deleted file mode 100644 index f9470d7c9869..000000000000 --- a/docs/introduction/what-is-cosmos.md +++ /dev/null @@ -1,7 +0,0 @@ -# What is Cosmos? - -Cosmos is a decentralized network of independent parallel blockchains, each powered by classical BFT consensus algorithms like [Tendermint](). - -The first blockchain in the Cosmos Network is the [Cosmos Hub](), whose native token is the Atom. Cosmos is a permission-less network, meaning that anybody can build a blockchain on it. - -Cosmos can interoperate with multiple other applications and cryptocurrencies. By creating a new zone, you can plug any blockchain system into the Cosmos hub and pass tokens back and forth between those zones, without the need for an intermediary. \ No newline at end of file diff --git a/docs/lotion/overview.md b/docs/lotion/overview.md deleted file mode 100644 index b28d2c75b41b..000000000000 --- a/docs/lotion/overview.md +++ /dev/null @@ -1,54 +0,0 @@ -# Overview - -Lotion is an alternative to the Cosmos SDK and allows you to create blockchain apps in JavaScript. It aims to make writing new blockchain apps fast and easy by using the ABCI protocol to build on top of Tendermint. Lotion lets you write secure, scalable applications that can easily interoperate with other blockchains on the Cosmos Network using IBC. - -Lotion itself is a tiny framework; its true power comes from the network of small, focused modules built upon it. Adding a fully-featured cryptocurrency to your blockchain, for example, takes only a few lines of code. - -For more information see the [website](https://lotionjs.com) and [GitHub repo](https://github.com/keppel/lotion), for complete documentation which expands on the following example. - -## Building an App - -### Installation - -::: tip -Lotion requires __node v7.6.0__ or higher, and a mac or linux machine. -::: - -``` -$ npm install lotion -``` - -### Simple App - -`app.js`: - -```js -let lotion = require('lotion') - -let app = lotion({ - initialState: { - count: 0 - } -}) - -app.use(function (state, tx) { - if(state.count === tx.nonce) { - state.count++ - } -}) - -app.listen(3000) -``` - -run `node app.js`, then: - -```bash -$ curl http://localhost:3000/state -# { "count": 0 } - -$ curl http://localhost:3000/txs -d '{ "nonce": 0 }' -# { "ok": true } - -$ curl http://localhost:3000/state -# { "count": 1 } -``` diff --git a/docs/reference/baseapp.md b/docs/reference/baseapp.md new file mode 100644 index 000000000000..3eaf1e2f7bf4 --- /dev/null +++ b/docs/reference/baseapp.md @@ -0,0 +1,14 @@ +# baseApp + +`baseApp` requires stores to be mounted via capabilities keys - handlers can only access stores they're given the key to. The `baseApp` ensures all stores are properly loaded, cached, and committed. One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the most recent state. + +`baseApp` distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`. The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees, +e.g. things that apply to all transaction from all modules), the later is the full state transition function. +During CheckTx the state transition function is only applied to the checkTxState and should return +before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated +gas cost. + +During DeliverTx the state transition function is applied to the blockchain state and the transactions +need to be fully executed. + +BaseApp is responsible for managing the context passed into handlers - it makes the block header available and provides the right stores for CheckTx and DeliverTx. BaseApp is completely agnostic to serialization formats. \ No newline at end of file diff --git a/docs/reference/store/README.md b/docs/reference/store/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/docs/resources/delegator-faq.md b/docs/resources/delegator-faq.md deleted file mode 100644 index 0de388a2c4ea..000000000000 --- a/docs/resources/delegator-faq.md +++ /dev/null @@ -1,69 +0,0 @@ -# Delegator FAQ - -## What is a delegator? - -People that cannot, or do not want to run [validator](/validators/overview.md) operations, can still participate in the staking process as delegators. Indeed, validators are not chosen based on their own stake but based on their total stake, which is the sum of their own stake and of the stake that is delegated to them. This is an important property, as it makes delegators a safeguard against validators that exhibit bad behavior. If a validator misbehaves, its delegators will move their Atoms away from it, thereby reducing its stake. Eventually, if a validator's stake falls under the top 100 addresses with highest stake, it will exit the validator set. - -Delegators share the revenue of their validators, but they also share the risks. In terms of revenue, validators and delegators differ in that validators can apply a commission on the revenue that goes to their delegator before it is distributed. This commission is known to delegators beforehand and can only change according to predefined constraints (see section below). In terms of risk, delegators' Atoms can be slashed if their validator misbehaves. For more, see Risks section. - -To become delegators, Atom holders need to send a "Bond transaction" from [Cosmos Voyager](/getting-started/voyager.md) where they specify how many Atoms they want to bond and to which validator. A list of validator candidates will be displayed in Cosmos Voyager. Later, if a delegator wants to unbond part or all of its stake, it needs to send an "Unbond transaction". From there, the delegator will have to wait 3 weeks to retrieve its Atoms. - -## Choosing a validator - -In order to choose their validators, delegators have access to a range of information directly in Cosmos Voyager. - -* Validator's name: Name that was chosen by the validator candidate when it declared candidacy. -* Validator's description: Description that was provided by the validator candidate when it declared candidacy. -* Validator's website: Link to the validator's website. -* Initial commission rate: The commission rate on revenue charged to any delegators (see below for more detail). -* Commission change rate: The maximum daily increase of the validator's commission -* Maximum commission: The maximum commission rate which this validator candidate can charge. -* Minimum self-bond amount: Minimum amount of Atoms the validator candidate need to have bonded at all time. If the validator's self-bonded stake falls below this limit, its entire staking pool (i.e. all its delegators) will unbond. This parameter exists as a safeguard for delegators. Indeed, when a validator misbehaves, part of its total stake gets slashed. This included the validator's own stake as well as its delegators' stake. Thus, a validator with a high amount of self-bonded Atoms has more skin-in-the-game than a validator with a low amount. The minimum self-bond amount parameter guarantees to delegators that a validator will never fall below a certain amount of self-bonded stake, thereby ensuring a minimum level of skin-in-the-game. - -## Directives of delegators - -Being a delegator is not a passive task. Here are the main directives of a delegator: - -* Perform careful due diligence on validators before delegating. If a validator misbehaves, part of its total stake, which includes the stake of its delegators, can be slashed. Delegators should therefore carefully select validators they think will behave correctly. -* Actively monitor their validator after having delegated. Delegators should ensure that the validators they're delegating to behaves correctly, meaning that they have good uptime, do not get hacked and participate in governance. They should also monitor the commission rate that is applied. If a delegator is not satisfied with its validator, it can unbond or switch to another validator. -* Participate in governance. Delegators can and are expected to actively participate in governance. A delegator's voting power is proportional to the size of its stake. If a delegator does not vote, it will inherit the vote of its validator. Delegators therefore act as a counterbalance to their validators. - -## Revenue - -Validators and delegators earn revenue in exchange for their services. This revenue is given in three forms: - -* Block provisions (Atoms): They are paid in newly created Atoms. Block provisions exist to incentivize Atom holders to stake. The yearly inflation rate fluctuates around a target of 2/3 bonded stake. If the total bonded stake is less than 2/3 of the total Atom supply, inflation increases until it reaches 20%. If the total bonded stake is more than 2/3 of the Atom supply, inflation decreases until it reaches 7%. This means that if total bonded stake stays less than 2/3 of the total Atom supply for a prolonged period of time, unbonded Atom holders can expect their Atom value to deflate by 20% per year. -* Block rewards ([Photons](https://blog.cosmos.network/cosmos-fee-token-introducing-the-photon-8a62b2f51aa): They are paid in Photons. Initial distribution of Photons will take the form of a hard spoon of the Ethereum chain. Atom holders will vote on the parameter of this hard spoon, like the date of the snapshot or the initial distribution. Additionally, bonded Atom holders will receive newly created Photons as block rewards. Photons will be distributed at a fixed rate in proportion to each bonded Atom holder's stake. This rate will be decided via governance. -* Transaction fees (various tokens): Each transfer on the Cosmos Hub comes with transactions fees. These fees can be paid in any currency that is whitelisted by the Hub's governance. Fees are distributed to bonded Atom holders in proportion to their stake. The first whitelisted tokens at launch are Atoms and Photons. - -## Validator's commission - -Each validator's staking pool receives revenue in proportion to its total stake. However, before this revenue is distributed to delegators inside the staking pool, the validator can apply a commission. In other words, delegators have to pay a commission to their validators on the revenue they earn. Let us look at a concrete example: - -We consider a validator whose stake (i.e. self-bonded stake + delegated stake) is 10% of the total stake of all validators. This validator has 20% self-bonded stake and applies a commission of 10%. Now let us consider a block with the following revenue: - -* 990 Atoms in block provisions -* 10 Photons in block reward -* 10 Atoms and 90 Photons in transaction fees. - -This amounts to a total of 1000 Atoms and 100 Photons to be distributed among all staking pools. - -Our validator's staking pool represents 10% of the total stake, which means the pool obtains 100 Atoms and 10 Photons. Now let us look at the internal distribution of revenue: - -* Commission = `10% * 80% * 100` Atoms + `10% * 80% * 10` Photons = 8 Atoms + 0.8 Photons -* Validator's revenue = `20% * 100` Atoms + `20% * 10` Photons + Commission = 28 Atoms + 2.8 Photons -* Delegators' total revenue = `80% * 100` Atoms + `20% * 10` Photons - Commission = 72 Atoms + 7.2 Photons - -Then, each delegator in the staking pool can claim its portion of the delegators' total revenue. - -## Risks - -Staking Atoms is not free of risk. First, staked Atoms are locked up, and retrieving them requires a 3 week waiting period called unbonding period. Additionally, if a validator misbehaves, a portion of its total stake can be slashed (i.e. destroyed). This includes the stake of their delegators. - -There are 3 main slashing conditions: - -* Double signing: If someone reports on chain A that a validator signed two blocks at the same height on chain A and chain B, this validator will get slashed on chain A -* Unavailability: If a validator's signature has not been included in the last X blocks, the validator will get slashed by a marginal amount proportional to X. If X is above a certain limit Y, then the validator will get unbonded -* Non-voting: If a validator did not vote on a proposal and once the fault is reported by a someone, its stake will receive a minor slash. - -This is why Atom holders should perform careful due diligence on validators before delegating. It is also important that delegators actively monitor the activity of their validators. If a validator behaves suspiciously or is too often offline, delegators can choose to unbond from it or switch to another validator. Delegators can also mitigate risk by distributing their stake across multiple validators. diff --git a/docs/resources/diagrams/todo.md b/docs/resources/diagrams/todo.md deleted file mode 100644 index b032b55cf1cb..000000000000 --- a/docs/resources/diagrams/todo.md +++ /dev/null @@ -1,17 +0,0 @@ -The following diagrams should be created to aid in comprehension of the SDK: - - Genesis circuit - - App structure (aka use of baseapp in something like gaia) - - Simulation framework - - Slashing Mechanism - - Staking Mechanism - - Staking/Slashing Mechanism specific to use of hooks - - Governance Mechanism - - Distribution Mechanism - - Inflation Mechanism (easier) - - IBC Mechanism - -These diagrams should reference specific structs/interfaces from the codebase, -logic flow and interconnectivity with other mechanisms etc. It's recommended that -https://www.draw.io/ be used, hence the raw diagram xml can be saved directly to -the Cosmos-SDK repo and adapted with the codebase. - diff --git a/docs/resources/faq.md b/docs/resources/faq.md deleted file mode 100644 index 91d902dbbeb7..000000000000 --- a/docs/resources/faq.md +++ /dev/null @@ -1,95 +0,0 @@ -# FAQ - -## Overview - -### How do I get Atoms? - -If you participated in the fundraiser, you can check your suggested atom balance at [fundraiser.cosmos.network](https://fundraiser.cosmos.network). -If not, you must wait until the [Cosmos Network launches](/roadmap) and Atoms are traded on exchanges. - -### Are Atoms listed on exchanges? - -No. The Cosmos Network mainnet has not yet launched, which means Atoms are _not_ on exchanges. $CMOS and $ATOM tokens are _not_ Cosmos Network native tokens. - -### How do I participate in the fundraiser? - -The [fundraiser](https://fundraiser.cosmos.network) is closed. The Interchain Foundation raised funds from private individuals and has hosted a public fundraising event on which ended on April 6, 2017. Both $ETH and $BTC were accepted in the fundraiser. The security of the fundraising process has been vetted extremely carefully. - -### What is the initial allocation of Atoms? - -As a public, decentralized network, the allocation of Atoms is decided by those who run the software for the Cosmos Hub. To faciliate a decision, we are creating a Swiss non-profit, the [Interchain Foundation](https://interchain.io), which is responsible for co-ordinating fundraising and allocating funds to get the network off the ground. The foundation will suggest a allocation of Atoms according to the results of the fundraiser. Users will ultimately decide the distribution for themselves when they run the software. - -The Interchain Foundation will suggest that 5% of the Atoms go to its initial donors, 10% go to the Interchain Foundation, 10% go to the company developing most of the software, and the remaining 75% to be distributed according to the results of the private and public fundraisers. - -### What is the team developing the Cosmos Network? - -The Cosmos Network is the first project being funded by the Interchain Foundation. Its development is led primarily by the [Tendermint team](/about/team). - -### What's the difference between Tendermint, the Cosmos Network, and the Cosmos Hub? - -- [Tendermint](https://tendermint.com) is a general purpose blockchain engine that uses a Byzantine-fault tolerant consensus protocol and allows applications to be written in any programming language. -- The Cosmos Network is a heterogenous network of Proof-of-Stake blockchains that can interoperate with one-another. -- The Cosmos Hub is the first Proof-of-Stake blockchain to be launched by the Cosmos Network; it uses Tendermint consensus, contains a built in governance protocol, and serves as co-ordinater for interoperability between other blockchains. -- Atoms: The native cryptocurrency on the Cosmos Hub. Atoms are necessary for participating in the consensus protocol and transacting on the network. - -### When will the Cosmos Network launch? - -Please check [our roadmap](https://cosmos.network/roadmap). - -### What is the utility of Atoms? - -Public, decentralized networks require high levels of security and spam-prevention that are best achieved by economic means: participants in the consensus must incur some economic cost, and all transactions processed by the network must pay a fee. Since we want to use Proof-of-Stake validators instead of Proof-of-Work miners, we require validators of the Cosmos Hub to make a large security deposit in Atoms - if they misbehave, their Atoms are revoked by the protocol! - -The more Atoms in security deposits, the more stake on the line; the more skin-in-the-game; the greater the economic security. In this sense, the Atoms act like virtual miners. - -To achieve spam-prevention, all transactions on the Cosmos Hub must pay a fee in Atoms. The fee may be proportional to the amount of computation required by the transaction, similar to Ethereum's concept of "gas". The fees are collected by the validators and distributed proportionately to the Atoms held in security deposits. - -## Interoperability - -### What's an IBC packet? - -[IBC packets](https://blog.cosmos.network/developer-deep-dive-cosmos-ibc-5855aaf183fe) are packets of data that one blockchain wishes to send to another blockchain. But instead of literally sending a packet of bytes via the TCP/IP or UDP/IP protocol (which is designed for singular, physical, machines), IBC packets require cryptographic proof-of-existence. Since no single node or validator has the authority to speak on behalf of the entire blockchain, and, since we don't want to rely on the integrity of the IP internet infrastructure, instead we rely on a cryptographic proof of a blockchain hash commit (+2/3 of signatures for that blockchain hash) along with a Merkle-proof from the aforementioned blockhash to a packet in the blockchain's "application state", which proves that the blockchain validators agreed to publish this packet of information. So, anyone who sees an IBC packet (regardless of the source of this data) can verify its integrity. - -### How does one exchange currencies in this system? - -For tokens outside the Cosmos system, they can only be introduced via pegged -derivatives. Read about interoperating with existing blockchains here: [Peggy](https://blog.cosmos.network/the-internet-of-blockchains-how-cosmos-does-interoperability-starting-with-the-ethereum-peg-zone-8744d4d2bc3f). - -``` - _ peg smart contract - / - [ Ethereum ] <--> [ EtherCosmos Peg Zone ] <-IBC-> [ Cosmos Hub ] <-IBC-> (Bitcoin) [ PoW/Casper ] - [ Tendermint ] [ Tendermint ] <-IBC-> (exchange) -``` - -### How does Cosmos manage governance? - -In Cosmos, the stakeholders are well defined, as is the prior social contract. Ethereum had a hard time with the fork because they had to ask the ether holders as well as the miners, but the ether holders had no prior social contract or obligation to partake in governance, so no quorum could be reached in time. Asking the miners is necessary to ensure that the hard-fork will have support, but after a while they tend to simply follow the money and incentives. - -Cosmos is different because instead of anonymous miners we have social contract bound validators and delegators who have stake, and, they have the obligation to partake in governance. - -## Validators - -### What is the maximum number of validators in Cosmos? What about nodes? - -We will start with 100 validators. Anyone else can be a node. To start, the validators will be the same across all shards - they will run the shards concurrently. Over time, these restrictions will be loosened. Misbehaviour in the consensus on any shard will result in security deposits being revoked. - -### What will be the process for abandoning validators that misbehave? - -If a validator misbehaves on its own by double-signing at the same height & round, then the evidence is very short and simple -- it's just the two conflicting votes. This evidence can be included in the the Cosmos Hub as a Slash transaction, and the validator will immediately become inactive and slashed after the Slash transaction gets committed. - -If there is a zone fork, either of the Cosmos Hub or any of the zones, the two conflicting commits also constitute evidence. This is a much more complicated data structure. It is guaranteed to slash at least 1/3 of the validators' atoms for that zone. - -### What's the difference between a Delegator and a Validator? - -A [validator](/staking/validators) has an active key involved in signing votes in the consensus protocol. A validator must also have some Atoms in a security deposit. Since there will only be a limitted number of validators, [other Atom holders can delegate](/staking/delegators) to the validators, thereby contributing to the economic security of the system by putting their funds on the line if the validator misbehaves. In return, they earn a share of the transaction fees and any inflationary rewards. - -### Can delegators also be validators? - -Delegators are never validators. If a validator wishes to delegate, they need to do so with their free and unbonded Atoms. - -### How are validator voting powers determined and changed? - -Validators are initially determined according to a public vote among Atom holders to be carried out before the launch of the Cosmos Hub. Atom holders delegate to the various candidates, and the top 100 candidates will be the initial validators. Once [the Hub launches](/roadmap), the vote will be a continuous process where users shuffle around their delegated Atoms, thereby changing the validator set. - -Part of the purpose of the fundraiser is to distribute Atoms across a wide variety of individuals and organizations so that the validator set will be sufficiently decentralized for a robust network. In the event of attacks or mishaps, the blockchain may need to purge bad actors through socially co-ordinated hard-forks. The ability to account for misbehaviour and co-ordinate hardforks helps make the system antifragile. diff --git a/docs/resources/whitepaper-ko.md b/docs/resources/whitepaper-ko.md deleted file mode 100644 index f87460c4ca40..000000000000 --- a/docs/resources/whitepaper-ko.md +++ /dev/null @@ -1,756 +0,0 @@ -# 코스모스 - -분산원장 네트워크 - -**저자:** - -Jae Kwon <mailto:jae@tendermint.com><br> -Ethan Buchman <mailto:ethan@tendermint.com> - -For discussions, [join our community chat](https://riot.im/app/#/room/#cosmos:matrix.org)! - -**번역 및 제작:** - -한승환, 이승민, 김기현, 윤승완, HJ Kim(금마), 김석현 - -\[[toc]] - -## 서 론 (Introduction) - -오픈 소스 생태계, 탈중앙화 파일 공유, 퍼블릭 암호화폐 등이 연달아 성공하면서 탈중앙화 인터넷 프로토콜들이 사회경제적 인프라를 근본적으로 개선하는데 사용될 수 있다는 것을 알게 되었다. 비트코인[\[1\]](https://bitcoin.org/bitcoin.pdf)(암호화폐)과 제로캐시[\[2\]](http://zerocash-project.org/paper)(프라이버시용 암호화폐) 같은 특화된 블록체인 어플리케이션들이 있었고, Augur(예측 시장)와 TheDAO[\[4\]](https://download.slock.it/public/DAO/WhitePaper.pdf)(투자 클럽) 같은 무수한 분산 애플리케이션들을 가진 이더리움(Ethereum)[\[3\]](https://github.com/ethereum/wiki/wiki/White-Paper) 같은 범용 스마트 컨트랙트 플랫폼들이 있었다. - -그러나 지금까지 이런 블록체인들은 엄청난 에너지 비효율, 형편없거나 제한적인 성능, 미성숙한 거버넌스 메커니즘 등을 비롯해 많은 결함들을 경험해왔다. 세그위트(Segregated-Witness)[\[5\]](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)와 비트코인 NG(BitconNG)[\[6\]](https://arxiv.org/pdf/1510.02037v2.pdf) 같은 비트코인 이체 처리량을 확장하기 위한 여러 제안들이 있었지만, 완전 감사가능성(complete auditability)을 희생하지 않는 이상, 여전히 단일한 기계의 용량에 제한을 받는 수직적 스케일링 솔루션이다. 라이트닝 네트워크(Lightning Network)[\[7\]](https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf)는 원장에서 특정한 이체들을 완전히 제외하여 비트코인의 확장성에 도움을 주며, 소액결제와 프라이버시 보호형 지급 플랫폼(privacy preserving payment rails)에 적합하지만, 보다 범용적인 확장에는 적합하지 않을 수 있다. - -가장 이상적인 해결책은 다수의 병렬 블록체인들이 각자의 보안 특성을 유지하면서 호환되는 것이다. 하지만 작업증명의 경우, 이것이 불가능은 아니더라도 상당히 어렵다는 것이 증명되었다. 예를 들어, 병합채굴(merged-mining)은 부모체인의 보안을 위해 수행된 작업을 자녀체인에서 재사용하는 것을 허용하지만, 이체들은 여전히 차례대로 각 노드에 의해 검증돼야 하고, 부모체인의 해시파워 대부분이 자녀체인에서도 병합채굴을 하고 있지 않을 경우, 병합 채굴된(merged mined) 블록체인이 공격에 취약해진다. 우리는 [대안 블록체인 네트워크 아키텍처들(alternative blockchain network architectures)](http://vukolic.com/iNetSec_2015.pdf)에 대한 학술적 고찰을 하였고, 그 중 일부에 대해서는 요약과 결점들을 아래의 [관련 연구(Related Work)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#related-work)에서 다루었다. - -우리는 이 모든 문제들을 해결하는 새로운 블록체인 네트워크 아키텍처인 코스모스(Cosmos)를 제시하고자 한다. 코스모스는 존(zone)이라고 불리는 많은 독립된 블록체인들의 네트워크이다. 존은 텐더민트 코어(Tendermint Core)[\[8\]](https://github.com/tendermint/tendermint/wiki)를 통해 작동하는데, 텐더민트 코어는 일관적이고 안전한 고성능의 [유사](https://blog.cosmos.network/tendermint-vs-pbft-12e9f294c9ab?gi=7d54da26ffe)[PBFT](https://blog.cosmos.network/tendermint-vs-pbft-12e9f294c9ab?gi=c320a745ea23) 합의 엔진을 제공하며, 악의적인 공격자들에게 엄격한 [포크 책임(fork-accountability)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#fork-accountability)을 묻는다. 텐더민트 코어의 BFT 합의 알고리즘은 공개형 지분증명 블록체인들의 확장성을 확보하는데 적합하다. - -코스모스 상의 첫 번째 존을 코스모스 허브(Cosmos Hub)라고 부른다. 코스모스 허브는 단순한 거버넌스 메커니즘을 통해 네트워크가 적응하고 업그레이드 할 수 있게 하는 ‘다중 자산 지분증명 암호화폐(multi-asset proof-of-stake cryptocurrency)’이다. 그에 더해서, 코스모스 허브는 다른 존들을 연결함으로 확장될 수 있다. - -코스모스 네트워크의 허브와 존들은 블록체인 간 통신(IBC: inter-blockchain communication) 프로토콜을 통하여 상호 통신한다. 이 프로토콜은 블록체인들을 위한 일종의 가상 UDP 또는 TCP 역할을 한다. 토큰들은 존들 간 거래소의 유동성(exchange liquidity)없이도 안전하고 신속하게 하나의 존에서 다른 존으로 전송될 수 있다. 존들 간 토큰 전송은 코스모스 허브를 통과하며, 코스모스 허브는 각 존이 보유한 토큰 총액을 추적한다. 허브는 각 존을 다른 존들의 실패(failure)로부터 격리한다. 또한 누구든지 코스모스 허브에 새로운 존을 연결할 수 있기 때문에, 존들은 앞으로의 새로운 블록체인 혁신과의 장래 호환성도 확보한다. - -## 텐더민트 (Tendermint) - -본 절에서는 텐더민트 합의 프로토콜과 이를 통한 애플리케이션을 구축을 위해 사용되는 인터페이스를 다룬다. 상세한 내용은 [부록(appendix)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#appendix)참조 - -### 검증인 (Validators) - -전형적인 비잔틴 장애 허용 알고리즘들(BFT: Byzantine fault-tolerant algorithms)에서는 각 노드가 동일한 가중치를 갖는다. 텐더민트에서는 노드들이 ‘0 이상’의 *투표권(voting power)*을 가지며, 양(+)의 투표권을 갖는 노드들을 *검증인\*\*(validators)*라고 부른다. 검증인들은 다음 블록에 동의하는 암호서명(cryptographic signature), 즉 *투표(vote)*를 전파(broadcast)함으로써 합의 프로토콜에 참여한다. - -검증인(validator)들의 투표권은 제네시스(genesis) 당시에 결정되거나 블록체인에 의해 결정론적으로(deterministically) 변경되기도 한다. 예를 들어, 코스모스 허브와 같은 지분증명 애플리케이션에서는 투표권이 담보물로서 본딩된(bonded) 지분 토큰(staking token)의 양에 의해 결정될 수도 있다. - -_주: ⅔, ⅓ 과 같은 분수들은 모든 **검증인**들이 동등한 가중치를 갖지 않는 한, **검증인**들의 총수가 결코 아니라 총 투표권**에서 차지하는** **비중**을 가리킨다. 주: +⅔ 는 " ⅔ 초과"를 의미하**며**, ⅓+은 "⅓ 이상"을 의미한다._ - -### 합의 (Consensus) - -텐더민트는 DLS 합의 알고리즘에서 파생되는, 부분적 동기 BFT 합의 프로토콜(synchronous BFT consensus protocol)이다[\[20\]](http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf). 텐더민트는 단순함, 성능 그리고 [포크 책임(fork-accountability)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#fork-accountability)이 특징이다. 이 프로토콜은 공개되있고 고정된 세트의 검증인들(a fixed, known set of validators)을 요구하는데, 각 검증인 공개 키에 의해 식별된다. 검증인들은 한 번에 하나의 블록, 즉 이체 목록(a list of transactions)에 대해 합의를 시도한다. 블록에 대한 합의는 라운드(round)를 통해 진행된다. 각 라운드에는 블록을 제안하는 라운드 리더(round-leader), 즉 제안자(proposer)가 있다. 그 다음, 검증인들은 제안된 블록을 받아들일 것인지 또는 다음 라운드로 넘어갈 것인지에 대한 단계별 투표를 진행한다. 각 라운드의 제안자는 검증인 리스트(ordered list)에서 투표권에 비례해 결정론적으로 선택된다. - -프로토콜에 대한 세부정보는 [여기](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm)를 참조 - -텐더민트 보안은 압도적 다수결(+⅔)과 잠금 메커니즘(locking mechanism)을 통해 최적의 비잔틴 장애 허용을 사용하는 것으로부터 유래한다. 다음을 보장한다. - -- 안전성을 저해(violation of safety)하기 위해서는 ⅓+의 투표권이 비잔틴이어야 하고, ‘2 개를 초과하는 값들’이 커밋(commit)되어야 한다. - -- 프로토콜은 임의의 검증인들 세트가 안전성을 저해하는 데 성공하거나 또는 시도만 하더라도, 이들을 식별할 수 있다. 충돌하는 블록들에 찬성 투표 하거나 정당하지 않은 투표들을 전파하는 이들 모두가 포함된다. - -텐더민트는 강력한 보장들에 더해 성능면에서도 탁월하다. 5 개 대륙 7 개 데이터센터에 분산되어 있는 64 개 노드의 대중품 클라우드(commodity cloud)를 기준으로, 텐더민트 합의는 약 1~2 초의 커밋 지연속도(commit latencies)와 함께 초당 수천 개의 트랜잭션(transaction)를 처리한다. 특히, 검증인들이 실패하거나 악의적으로 조작된 투표를 전파하는 가혹한 공격 상황(adversarial conditions)에서도 초당 1,000 번 수준의 트랜잭션 성능은 가볍게 능가한다. _아래 그림 참조_ - -![Figure of Tendermint throughput performance](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/tendermint_throughput_blocksize.png) - -### 라이트 클라이언트 (Light Clients) - -텐더민트 합의 알고리즘의 특징은 단순화된 라이트 클라이언트 보안인데, 모바일 및 사물인터넷에 사용되기도 적합하다. 비트코인 라이트 클라이언트는 ‘블록헤더 체인’들을 동기화(sync)하여 가장 많은 작업증명을 가진 체인을 찾아야 하지만, 텐더민트 라이트 클라이언트는 ‘검증인 세트’의 변경을 추적해서, 최신 블록에서 +⅔ 프리커밋(PreCommit)을 검증하기만 하면 최신 상태를 결정할 수 있다. - -간결한 라이트 클라이언트 증명들은 [블록체인 간 통신(inter-blockchain communication)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#/h)도 가능하게 한다. - -### 공격 방지 (Preventing Attacks) - -텐더민트는 ‘[long-range-nothing-at-stake double spend](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#/h)’나 [검열(censorship)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#/h) 등을 방지하기 위한 다양한 보호장치를 가지고 있다. 세부사항은 [부록(appendix)](https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#/h)참조 - -### TMSP - -텐더민트 합의 알고리즘은 텐더민트 코어(Tendermint Core)라는 프로그램에서 구현된다. 텐더민트 코어는 모든 결정적 블랙박스 애플리케이션(deterministic blackbox application)을 분산 복제 블록체인(distributedly replicated blockchain)으로 전환시킬 수 있는 어플리케이션 어그노스틱(application-agnostic) "합의 엔진"이다. 아파치 웹 서버나 Nginx 가 CGI 나 FastCGI 를 통해 워드프레스 애플리케이션에 접속하는 것처럼, 텐더민트 코어는 텐더민트 소켓 프로토콜(TMSP: Tendermint Socket Protocol)을 통해 블록체인 애플리케이션들과 연결된다. - -비트코인을 예로 들어보자면, 비트코인은 각 노드가 완전 감사되는 UTXO(fully audited Unspent Transaction Output) 데이터베이스를 유지하는 암호화폐 블록체인이다. 만일 누군가 비트코인과 같은 시스템(Bitcoin-like system)을 TMSP 상에 만들고자 하면, ‘**텐더민트 코어**’는 아래와 같은 부분들을 책임진다. - -- 노드 간 블록 및 이체 공유 - -- 정규(canomical)/변경배제(immutable) 이체순서의 확립(블록체인) - -반면, ‘**TMSP 의 어플리케이션**’은 다음을 책임진다. - -- UTXO 데이터베이스 유지 - -- 이체의 암호서명 검증 - -- 존재하지 않는 이체를 지불방지 - -- 클라이언트들의 UTXO 데이터베이스에 대한 query 허용 - -텐더민트는 애플리케이션 프로세스와 합의 프로세스 사이에 매우 단순한 API 를 제공함으로써 블록체인 설계를 분해할 수 있다. - -## 코스모스 개요 (Cosmos Overview) - -코스모스는 독립 병렬 블록체인들의 네트워크이며, 해당 블록체인들은 각기 텐더민트와 같은 전형적인 BFT 합의 알고리즘에 기반한다[1]. - -코스모스의 최초 블록체인이 곧 코스모스 허브가 된다. 코스모스 허브는 블록체인 간 통신(IBC) 프로토콜을 통해 다른 많은 블록체인들(즉, _존들_)과 연결된다. 코스모스 허브는 수많은 유형의 토큰을 추적하고, 연결된 각 존의 토큰 총 수를 기록한다. 모든 존들 간의 코인 전송은 코스모스 허브를 거치기 때문에 토큰은 존들 간의 유동 거래소(liquid exchange) 방식 없이 - -이 아키텍처는 어플리케이션 상호운용성, 확장성 그리고 무결절 업그레이드 가능성(seamless upgradability)을 포함한 블록체인이 직면한 많은 문제들을 해결한다. 예를 들면, Bitcoind, Go-Ethereum, 크립토노트(CryptoNote), ZCash 등을 포함한 임의의 블록체인 시스템으로부터 파생된 존들이 코스모스 허브에 연결될 수 있다. 이러한 존들을 통해 코스모스는 전역 이체(global transaction) 요구를 충족시킬 때까지 무한히 확장할 수 있다. 그리고 존들은 탈중앙화 거래소(distributed exchange)에도 매우 적합하며, 실제로 지원될 것이다. - -코스모스는 단일 분산 원장에 불과한 것이 아니며, 코스모스 허브도 폐쇄형 플랫폼(walled garden, 울타리 친 정원)이 아니다. 오히려 코스모스는 미래 금융 시스템의 새로운 기초가 될 수 있는 개방형 분산원장 네트워크를 위한 프로토콜이며, 암호학 원리, 잘 설계된 경제(sound economics), 합의 이론, 투명성, 책임(accountability) 등의 원칙에 기반하고 있다. - -### Tendermint-BFT DPoS - -코스모스 허브는 텐더민트 BFT 합의 알고리즘에 기반하는, 코스모스 네트워크 내 최초의 퍼블릭 블록체인이다. 텐더민트 오픈 소스 프로젝트는 비트코인의 작업증명(PoW) 합의 알고리즘이 지닌 속도, 확장성, 환경 등의 문제를 처리하기 위해서 2014 년에 탄생했다. 1988 년 MIT 에서 개발한 증명된 BFT 알고리즘들을 활용하고 개선해서, 텐더민트 팀은 제 1 세대 지분증명(PoS) 암호화폐들이 겪은 Nothing-at-stake 문제를 해결하는 지분증명 암호화폐를 최초로 개념증명하였다. - -오늘날, 대부분의 비트코인 모바일 지갑들은 이체 검증(transaction verification)을 제공하는 신뢰할 수 있는 서버(trusted server)를 이용한다. 이는 PoS 가 여러번의 이체확인(confirmation)을 기다려야만, 이체확정된 것으로 간주되기 때문이다. 이중지불(double-spend) 공격이 이미 코인베이스(CoinBase) 같은 서비스들에서 일어난 바 있다. - -다른 블록체인 합의 시스템들과는 달리 텐더민트는 즉각적이고 안전한(provably-secure) 모바일-클라이언트 지불 검증을 제공한다. 텐더민트는 분기(fork)할 수 없도록 설계되었기 때문에, 모바일 지갑들에서 즉시 이체확인이 가능하며 실제로 신뢰 없는(trustless) 지불을 실현한다. 이는 IoT 관련 어플리케이션들에도 큰 영향을 줄 것이다. - -(비트코인 채굴자들과 유사한 역할이지만 그 대신에 암호서명을 통해 투표하는) 코스모스의 검증인들은 블록을 커밋 할 책임이 있는 안전한 전용 머신들이어야 한다. 검증인이 아닌 이들(non-validators)은 ‘아톰’이라고 부르는 지분 토큰(staking tokens)을 임의의 검증인에게 위임하여 일정한 블록 수수료(block fees)와 아톰 보상(atom rewards)을 얻을 수는 있으나, 위임 검증인(delegate validator)이 해킹당하거나 프로토콜을 위반할 경우, 처벌을 받게 되는 리스크가 있다. 텐터민트 BFT 합의의 입증된 안정성 보장과 (검증인 및 위임자) 주주들의 담보 보증(collateral deposit)은 노드들에 심지어는 라이트 클라이언트들에게 증명 가능하고 정량화 가능한 보안성(provable, quantifiable security)을 제공한다. - -### 거버넌스 (Governance) - -‘공개형 분산원장’은 헌법(constitution)과 거버넌스 시스템(governance system)을 가져야 한다. 비트코인은 업그레이드 등의 조정을 위해 일정 부분 비트코인 재단(Bitcoin Foundation)이나 채굴에 의존하지만, 진행속도가 느리다. 이더리움의 경우에는 The DAO 해킹의 처리를 위한 하드포크 후 ETH 와 ETC 로 분할되었는데, 이는 사전에 그런 의사결정을 하기 위한 사회적 계약이나 메커니즘이 존재하지 않았기 때문이다. - -코스모스 허브의 검증인과 위임자는 코스모스 허브의 정책들을 위한 ‘코드가 아니라 평이한 언어로 된 헌법(규칙)’을 표결에 부쳐 수정할 뿐 아니라 ‘블록 가스 한계(block gas limit)’ 같은 시스템의 사전에 설정된 제한들을 업그레이드를 통해 자동으로 변경하는 프로포잘(proposals)도 표결에 부칠 수 있다. 헌법은 The DAO 사건 같은 절도 및 버그관련 문제들의 이해관계자들이 응집(cohesion)할 수 있도록 도우며, 보다 신속하고 깔끔한 해결책이 나올 수 있도록 한다. - -각 존 역시 자체적인 헌법과 거버넌스 메커니즘을 가질 수 있다. 예를 들어, 코스모스 허브가 변경 배제(immutability) -코스모스 허브의 노드 실행 버그를 제외하고는 롤백 금지(no roll-backs)와 같은- 헌법을 적용한 경우라면, 각 존은 절도와 버그를 위한 롤백 관련 자체 정책을 설정할 수 있다. - -코스모스 네트워크는 상이한 정책의 존들 간 상호운용성을 확보함으로 사용자들에게 궁극적 자유와 실험의 기회를 제공한다. - -## 허브와 존 (The Hub and Zones) - -여기서는 탈중앙화(decentralization)와 확장성(scalability)의 새로운 모델을 설명한다. 코스모스는 텐더민트에 기반한 복수의 블록체인들의 네트워크이다. 기존의 프로포잘들이 전역적 이체 순서(total global transaction ordering)를 가진 ‘단일 블록체인’을 목표로 하는 반면에, 코스모스는 수많은 블록체인들이 상호 병행 실행(run concurrently)하는 동시에 상호운용성을 확보하도록 한다. - -기본적으로 코스모스 허브는 ‘존(zone)’이라고 부르는 여러 독립된 블록체인들을 관리한다(‘존’은 ‘샤드(shard)’로도 불림, 데이터베이스의 스케일링 기법인 ‘샤딩(sharding)’참조). 존들은 최근의 블록 커밋들을 끊임없이 허브로 전송하며, 허브는 이를 통해 항상 최신 상태를 유지한다. 마찬가지로, 각 존도 허브의 상태를 제공받는다(다만 허브를 통한 간접적인 경우를 제외하고는 존들끼리는 서로 이러한 작업을 하지 않는다). 존들은 정보의 송신과 수신의 증거인 머클 증명(Merkle-proofs)을 포스팅함으로 정보의 패킷들을 교환한다. 이 메커니즘을 ‘블록체인 간 통신(inter-blockchain communication)’ 또는 IBC 라고 칭한다. - -![Figure of hub and zones acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/hub_and_zones.png) - -어느 존이든 스스로 허브가 되어 비순환 그래프(acyclic graph)를 형성할 수 있으나 명료성을 위해 우리는 단지 하나의 허브와 많은 비-허브 존들이 존재하는 단순한 구성만 설명할 것이다. - -### 허브 (The Hub) - -코스모스 허브는 멀티자산 분산 원장(multi-asset distributed ledger)을 관리하는 블록체인인데, 여기서 토큰은 개인 사용자들이나 존 자체가 보유할 수 있다. 이 토큰들은 ‘코인 패킷(coin packet)’이라 부르는 특수 IBC 패킷을 통해 하나의 존에서 다른 존으로 이동할 수 있다. 허브는 존들에 걸쳐 각 토큰 총액의 전역적 불변성(global invariance)을 보존한다. IBC 코인 패킷 이체는 반드시 송신자, 허브 및 수신자 블록체인에 의해 커밋 되어야 한다. - -코스모스 허브는 전체 시스템을 위한 토큰의 ‘중앙 원장’ 역할을 하기 때문에, 보안이 무엇보다도 중요하다. 각 존은 단 4 명(혹은 BFT 합의가 필요하지 않을 경우에는 훨씬 더 적은 수)의 검증인으로도 안전해지는 텐더민트 블록체인일 수 있는 반면, 허브는 대륙 네트워크 분할(continental network partition)이나 국가 주도적 공격(nation-state sponsored attack) 같은 가장 심각한 공격 시나리오들에도 견딜 수 있어야 한다. 따라서 전역적으로 탈중앙화된 검증인 세트로 보안되어야 한다. - -### 존 (The Zones) - -코스모스 존은 허브와 IBC 메시지를 교환하는 독립 블록체인이다. 허브의 관점에서, 존은 IBC 패킷을 사용하여 토큰을 송수신할 수 있는 ‘멀티자산 동적구성원 멀티시그너처 계정(multi-asset dynamic-membership multi-signature account)’이다. 암호화폐 계정과 마찬가지로 존은 보유 중인 토큰보다 더 많은 토큰을 전송할 수 없지만, 토큰을 보유한 다른 존으로부터 토큰을 수신할 수는 있다. 존은 토큰 유형들의 ‘소스(source)’로 지정되어, 해당 토큰을 추가 공급할 수도 있다. - -코스모스 허브의 아톰들은 허브의 검증인이 아니라, ‘허브에 연결된 존의 검증인’들에 의해 스테이킹될 수도 있다. 이 존들에 대한 이중지불 공격은 텐더민트의 포크 책임인 아톰의 대폭 감소(slashing)라는 결과를 가져오게 되는 반면, 투표권의 +⅔ 이 비잔틴인 존이라면 무효한 상태(invalid state)를 커밋할 수 있다. 코스모스 허브는 다른 존들에 커밋 된 이체들은 검증하거나 실행하지 않으므로, 자신이 신뢰하는 존으로 토큰을 전송하는 것은 사용자들의 책임이다. 장래에는 코스모스 허브의 거버넌스 시스템이 존 실패(failures)를 위한 허브 개선 프로포잘을 만들수도 있다. 예를 들면, 공격이 탐지될 때, 일부(또는 전체) 존들의 아웃바운드 토큰 전송을 억제함으로 ‘긴급 서킷 브레이킹(토큰 전송 일시중단)’을 할 수도 있다. - -## 블록체인 간 커뮤니케이션 (Inter-blockchain Communication (IBC)) - -여기서는 허브와 존 간의 상호 통신방법을 설명한다. 예를 들어, ‘존 1(Zone 1)’, ‘존 2(Zone 2)’와 ‘허브(Hub)’의 세 블록체인이 있고, ‘존 1’이 ‘허브’를 통과하여 ‘존 2’로 가는 패킷을 만들고자 한다. 패킷이 하나의 블록체인에서 다른 블록체인으로 이동하기 위해, 송신 체인(sending chain)이 수신지로 가는 패킷을 발행했다는 증거를 수신 체인(receiving chain)에 포스팅한다. 수신 체인이 이 증거를 확인하기 위해서는 송신자의 블록 헤더(block headers) 정보를 알아야 한다. 이 메커니즘은 사이드체인(sidechain)이 사용하는 메커니즘과 유사한데, 상호 작용하는 두 체인이 ‘존재 증명 데이터그램의 양방향 스트림(a bidirectional stream of proof-of-existence datagram)’을 통해 서로를 ‘인식’해야한다 (이체). - -IBC 프로토콜을 두 가지 이체 방식을 통해 정의할 수 있다: 블록체인이 최근의 블록 해시를 임의의 관측자에게 증명하는 IBCBlockCommitTx 이체, 그리고 블록체인이 송신자의 어플리케이션이 패킷을 머클증명을 통해 최근 블록해시로 전파했다는 것을 증명하는 IBCPacketTx 이체 - -IBC 구동방식을 IBCBlockCommitTx 와 IBCPacketTx 로 분할함으로, 수신체인의 내부 수수료 시장 메커니즘(native fee market-mechanism)이 커밋될(승인될) 패킷을 결정하도록 하며, 송신체인이 얼마나 많은 아웃바운드 패킷들을 허용할 지 자유롭게 정할 수 있도록 한다. - -![Figure of Zone1, Zone2, and Hub IBC without acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_without_ack.png) - -위의 예에서, ‘존 1’의 블록해시를 (또는 ‘존 2’ 상의 ‘허브’의 블록 해시를) 업데이트 하기 위해서는, IBCBlockCommitTx 이체가 ‘존 1’의 블록해시와 함께 ‘허브’에 (또는 ‘허브’의 블록해시와 함께 ‘존 2’에) 반드시 포스팅 되어야 한다. - -_두 IBC 이체 유형에 관한 보다 상세한 정보는 [IBCBlockCommitTx](#ibcblockcommittx) 와 [IBCPacketTx](#ibcpacketcommit) 를 참조._ - -## 사용사례 (Use Cases) - -### 분산거래소 (Distributed Exchange) - -비트코인이 원장을 복사하고 분산하여 더 안전해지는 것처럼, 거래소도 블록체인 상에 올림으로 내/외부의 해킹으로부터 더욱 안전해질 수 있다. - -현재 커뮤니티에서 칭하는 탈중앙화 거래소(decentralized exchange)는 ‘아토믹 크로스체인(Atomic Cross-Chain, AXC)’ 이체에 기반하고 있다. 이를 통해 두 명의 유저는 두 개의 서로 다른 원장(체인)에서 이체를 일으키고 해당 이체는 동시에 각 원장에 기록되거나 또는 그 어떤 원장에도 기록되지 않는다. 예를 들어, AXC 를 이용하면 두 명의 유저가 서로의 이더와 비트코인(또는 서로 다른 원장의 토큰)을 교환할 수 있다. AXC 기반 거래소의 장점은, 두 명의 유저 모두 서로 또는 거래소 서비스를 신뢰할 필요가 없다는 점이다. 그러나 거래를 위해서는 양 당사자가 반드시 온라인 상태여야만 한다는 점이 치명적인 단점이다. - -또 다른 방식의 탈중앙화 거래소는 자체적인 분산원장에서 작동하는 ‘대규모의 복제 분산 거래소(a mass-replicated distributed exchange)’이다. 유저는 ‘지정가 주문(limit order)’을 내고 컴퓨터를 종료한다. 이 경우, 유저가 온라인 상태가 아니어도 거래가 성사된다. 블록체인이 해당 거래를 매칭시키고 완료시키는 것이다. - -중앙화된 거래소의 경우, 이미 많은 지정가 주문이 걸려 있고 따라서 유저들을 더 쉽게 유치하게 된다. 거래소에서 유동성은 더 큰 유동성을 야기하고 강한 네트워크 효과(또는 승자독식)를 일으키게 된다. 현재 24 시간 거래량 기준, Poloniex 가 $20M 으로 가장 많은 거래량을 가지고 있고, Bitfinex 가 $5M 로 그 다음에 위치하고 있다. 이러한 사례를 생각해보면, AXC 기반의 새로운 탈중앙화 거래소가 중앙화된 거래소를 이길 가능성은 거의 없다. 탈중앙화된 거래소가 중앙화된 거래소와 경쟁하기 위해서는 많은 거래량을 확보해야 한다. 오직 ‘분산 거래소(distributed exchange)’만이 그것을 가능하게 할 수 있다. - -텐더민트는 또한 매우 빠른 이체 커밋을 제공한다. 일관성의 훼손없이 빠른 완결성을 우선순위에 둠으로써 코스모스 상의 존(zone)들의 이체를 빠르게 완결한다. 이는 거래소의 이체나 IBC 를 통한 존들 간의 이체에 동일하게 적용된다. - -현재 암호화폐 거래소들의 상황을 고려할 때, 코스모스를 이용해 분산거래소(일명 ‘코스모스 덱스’)를 만드는 것은 매우 적절하다. 코스모스 덱스(Cosmos DEX)의 이체 처리량과 커밋 속도는 중앙화된 거래소에 필적한다. 유저들은 지정가 주문을 올리고, 이 주문은 당사자의 온라인 상태여부에 관계없이 완결된다. 트레이더들은 텐더민트, 코스모스 허브, 그리고 IBC 를 통해, 빠른 속도로 자금을 존(zone)들이나 거래소로 이동시킬 수 있다. - -### 다른 화폐에 가치고정 (Pegging to Other Cryptocurrencies) - -특권 존(privileged zone)은 다른 암호화폐를 페깅한 토큰의 소스 역할을 할 수 있다. 페그(peg)는 코스모스 허브와 존의 관계와 본질적으로 유사한데, 코스모스 허브와 존 모두는 토큰이 한 쪽에서 다른 쪽으로 이동했다는 증명을 검증하기 위해 상대방의 최신 블록을 반드시 알고 있어야 한다. 코스모스 네트워크의 페그 존(peg-zone)은 다른 암호화폐뿐 아니라 허브도 추적한다. 페그 존을 통한 간접참조(indirection)는 허브의 로직이 단순하면서도 비트코인의 작업증명 채굴 같은 다른 블록체인 합의 전략들에 독립적(agnostic)인 상태를 유지할 수 있게 한다. - -예를 들어, 허브의 검증인 세트와 동일한 어떤 검증인 세트를 갖는 존이 이더-페그(ether-peg) 역할을 할 수 있을 것이다. 여기서 ‘페그-존(peg-zone)’의 TMSP 애플리케이션은 ‘외부 이더리움 블록체인의 페그 컨트랙트(peg contract)’와 IBC 메시지를 교환할 수 있다. 이더 보유자들이 이더리움 상의 페그 컨트랙트로 이더를 전송함으로 코스모스의 페그 존에 이더를 전송하게 된다. 이렇게 이더가 일단 한번 수신되면, 페그 컨트랙트가 페그 존으로부터 IBC 패킷을 수신하지 않는 한 이더는 인출되지 못 한다. 페그 컨트랙트에서 특정 이더리움 계정으로부터 이더를 수신했다는 IBC 패킷을 페그 존으로 보내면, 이에 대응되는 계정이 동일한 잔고와 함께 페그 존 위에 생성된다. 페그 존 위의 (페깅된) 이더를 허브로 또는 허브로부터 전송할 수 있으며, 페깅 이더를 폐기하면서 이더리움 상의 특정 인출 주소로 그 이더를 도로 전송할 수 있고, 이더의 인출을 허용하기 위해 페그 존에서 이체가 발생했음을 증명하는 IBC 패킷을 이더리움 페그 컨트랙트에. - -물론 그런 페깅 컨트랙트는 악의적 검증인 세트를 통한 리스크에 노출되어 있다. ⅓+ 비잔틴 투표권이 분기(fork)를 만들어 페깅된 이더를 페그 존에 유지하는 동시에 이더리움 위의 페그 컨트랙트를 통해 이더를 인출할 수도 있다. 더 좋지 않은 시나리오는 +⅔ 비잔틴 투표권이, 페그 존의 원래 페깅 로직으로부터 이탈하여, 페그 컨트랙트로 보내지는 모든 이더를 노골적으로 훔칠 수도 있다는 것이다. - -이런 문제들은 페그를 ‘완전 책임적(totally accountable)’으로 설계하여 해결할 수 있다. 예를 들면, 허브나 원점(페깅될 토큰의 원래 블록체인)으로부터의 모든 IBC 패킷이 페그-존의 응답(acknowledgment)을 요구하도록 할 수도 있을 것이다. 허브와 원점은 페그-존 검증인들이 담보물(collateral)을 포스팅(post) 할 수 있게 하고, 독립 감사들(independent auditors)의 도전을 허용하기 위해 페그 컨트랙트로부터 나가는 토큰 전송은 지연되도록 하는 식이다. 그리고 담보 언본딩(unbonding) 기간은 충분히 길어야 한다. 이 부분은 미확정 상태로 두고, 누구든지 향후에 관련 제안을 해서 코스모스 거버넌스 시스템에 승인을 받아 적용할 수 있도록 한다. - -정치사회적 분위기가 아직은 갖추어져 있지 않긴 하지만, 국가 통화의 책임기관들, 특히 은행들의 조합으로부터 검증인 세트를 형성함으로 국가의 법정통화에 페깅하는 존들을 허용할 수도 있다. 물론, 강력한 법체계에 기반하는 화폐만 허용하도록 충분한 고려가 되어야 할 것이며, 충분히 큰 규모의 공증인이나 기관들을 통해 감사시스템을 강제하여 은행들의 활동을 관리해야할 것이다. - -이렇게 통합이 된다면, 참여 은행에 은행계좌가 있는 누구든지 존에 있는 은행계좌로부터 존에 있는 다른 계좌나 허브나 혹은 또 다른 존으로 법정화폐를 자유롭게 이동시킬 수 있을 것이다. 이 점에서 코스모스 허브는 법정화폐들과 암호화폐들 간의 전달자 역할을 하고, 지금까지 상호운용성을 거래소(exchanges)의 영역으로 한정시킨 장벽들을 제거할 수 있다. - -### 이더리움 확장성 (Ethereum Scaling) - -이더리움의 해결되지 않은 쟁점 하나는 스케일링 문제를 해결하는 방법이다. 현재는 각 이더리움 노드들이 모든 이체를 처리하고 또 모든 상태를 저장한다. [링크](https://docs.google.com/presentation/d/1CjD0W4l4-CwHKUvfF5Vlps76fKLEC6pIwu1a_kC_YRQ/mobilepresent?slide=id.gd284b9333_0_28) - -텐더민트는 이더리움의 작업증명보다 훨씬 빠르게 블록들을 커밋 할 수 있기 때문에, 텐더민트 합의에 기반한 페깅된 이더(pegged-ether)를 운용하는 EVM 존들은 이더리움 블록체인에 보다 높은 성능을 제공할 수 있다. 뿐만 아니라, 비록 코스모스 허브 및 IBC 패킷 자체는 임의계약 로직 실행을 허용하지 않지만, 서로 다른 존들에서 실행되는 이더리움 컨트랙트 간 토큰이동의 조정을 위해 사용되며, 샤딩(sharding)을 통한 토큰 중심 이더리움 스케일링을 위한 기반을 제공할 수 있다. - -### 멀티 어플리케이션 통합 (Multi-Application Integration) - -코스모스 존들은 존의 생성 초기에 정해진 어플리케이션 로직에 따라 작동하며, 거버넌스를 통해 지속적으로 업데이트될 수 있다. 그런 유연성 덕분에 코스모스 존들이 이더리움이나 비트코인 같은 다른 암호화폐들의 페그 역할을 하고, 동일한 코드베이스를 활용하면서도 상이한 검증인 세트와 초기 분포(initial distribution)를 갖는 블록체인 파생상품(derivatives)을 만들 수 있다. 이를 통해 이더리움, 제로캐시, 비트코인, 크립토노트 등과 같은 기존의 암호화폐 프레임워크들이 ‘고성능 합의 엔진(텐더민트 코어)’을 통해 공통의 네트워크에서 사용될 수 있으며, 엄청난 상호운용성의 기회를 가질 수 있게 된다. 뿐만 아니라, 멀티 자산 블록체인으로서, 단일 이체는 다수의 인풋과 아웃풋을 포함할 수 있고, 어떤 토큰이든지 인풋이 될 수 있기 때문에, 주문들은 다른 플랫폼들을 통해 매칭되더라도 코스모스가 직접 탈중앙화 거래소(exchange)를 위한 플랫폼 역할을 할 수 있다. 또한 존은 오더북 기능이 있는 ‘분산형 장애-허용 거래소’ 역할을 할 수도 있는데, 해킹 공격에 당하곤 하는 기존의 중앙집중형 암호화폐 거래소들에 대한 강력한 개선책이 될 수 있다. - -존은 또한 기업 및 정부 시스템들의 블록체인 버전(blockchain-backed versions)을 지원할 수도 있다. 전통적으로 조직에 의해 운영된 서비스에 대해서 기반이 된느 부분은 통제권을 유지하고, 특정 부분만을 존 위의 TMSP 애플리케이션으로 운영한다면, 퍼블릭 코스모스 네트워크의 보안과 상호운용성을 활용할 수 있게 된다. 따라서 코스모스는 블록체인 기술을 활용하고자 하지만 (분산된) 제 3 자에게 통제를 완전히 내주는 것은 경계하는 조직들에 일거양득을 제공할 수 있다. - -### 네트워크 분할 완화 (Network Partition Mitigation) - -일각에서는 텐더민트 같은 ‘일관성선호 합의 알고리즘(consistency-favouring consensus algorithm)’에 심각한 문제가 있다고 주장한다. +⅔ 투표권(⅓+은 오프라인)을 갖는 분할이 생기지 않도록 방지하는 것이 합의과정 자체를 멈추도록 할 수 있다는 것이다. 코스모스 아키텍처는 지역 자치 존(regional autonomous zone)을 갖는 전역 허브(global hub)를 사용함으로 이 문제를 완화할 수 있는데, 이 지역적 자치 존은 각 존의 투표권이 지리적 위치에 기초하여 분배되는 존을 가리킨다. 예를 들어, 개별 도시들이나 지역들이 자체적인 존을 운영하면서 공통의 허브(예. 코스모스 허브)를 공유하여, 일시적인 네트워크 분할로 허브가 중단되더라도 자치활동은 지속될 수 있도록 할 수 있다. 강인한 연합형 장애허용 시스템(robust federated fault-tolerant system)이 설계되기 위해서는 실제 지리, 정치 및 네트워크 토폴로지 관련 특징들이 고려되어야 할 것이다. - -### 연합 명칭 결의 시스템 (Federated Name Resolution System) - -네임코인(NameCoin)은 비트코인 블록체인을 이용하여 ‘명칭 결의(name-resolution)’ 문제를 해결하고자 한 최초의 블록체인 중 하나였다. 안타깝지만 이 접근법에는 몇 가지 문제들이 있었다. - -네임코인으로 예를 들면, *@satoshi*라는 명칭이 과거 어느 시점에 특정 공개키로 등록되었다는 것은 검증할 수 있지만, 이후의 모든 블록들을 다운로드 하지 않는 한 그 공개키가 이후로 업데이트 된 적이 있는지는 알 수 없다. 이는 비트코인의 UTXO 머클화 모델의 한계 때문인데, 이 모델에서는 ‘상태’가 아닌 ‘이체의 기록’만 블록 해시로 머클화된다--이는 존재를 증명하지만, 이후로 업데이트가 없었다는 것을 증명하지는 못한다. 따라서 완전 노드를 신뢰하거나 전체 블록체인을 다운로드 하면서 상당한 비용을 지불해야만 가장 최근 값을 확실히 알 수 있다. - -머클 탐색 트리(Merkle-ized search tree)가 네임코인에 구현되더라도, 작업증명에 대한 의존성 때문에 라이트 클라이언트 검증에서 문제가 생긴다. 라이트 클라이언트는 전체 블록체인의 블록헤더들(또는 적어도 마지막 업데이트 이후의 모든 헤더들)을 모두 다운로드 해야 한다. 이는 대역폭 사용이 소모시간과 함께 선형으로 증가한다는 것을 의미한다[\[21\]]][21]. 또한 작업증명 블록체인 위의 명칭 변경을 위해서는 추가적인 블록확인을 기다려야 하는데 이것이 비트코인에서는 최대 1 시간까지도 걸릴 수 있다. - -텐더민트의 경우, 변경을 위해 필요한 것은 (투표권을 통해) 검증인 정족수가 서명한 최근의 블록 해시, 그리고 명칭에 대한 현재 값(current value)의 머클 증명이다. 이를 통해, ‘명칭 값’을 간결하고 신속하며 안전한 라이트 클라이언트 검증을 할 수 있다. - -코스모스에서 이 개념을 확장시킬 수 있다. 코스모스의 각 명칭등록 존(name-registration zone)은 ‘.com’이나 ‘.org’와 같은 최상위 도메인(TLD: top-level-domain)을 가질 수 있고, 자체적인 거버넌스와 등록규칙을 설정할 수 있다. - -## 발행과 인센티브 (Issuance and Incentives) - -### 아톰 토큰 (The Atom Token) - -코스모스 허브는 ‘다중자산 분산원장’이며 특별한 내부 토큰인 ‘_아톰(atom)_’을 가지고 있다. 아톰은 코스모스 허브의 유일한 지분 토큰(staking token)이다. 아톰은 보유자가 투표, 검증 또는 다른 검증인들에게 위임을 하기 위해 필요하다. 이더리움의 이더와 마찬가지로 아톰 역시 스팸공격 완화를 위한 이체수수료(transaction fees) 지불을 위해 사용될 수 있다. 추가되는 인플레이션 아톰(inflationary atoms)과 블록 이체수수료가 검증인들에게 그리고 검증인들에게 위임한 위임자들(delegators)에게 보상된다. - -BurnAtomTx 이체 기능을 통해 ‘지급 준비금 풀(reserve pool)’에서 일정 비율의 토큰 금액(proportionate amount of tokens)을 회수(recover)할 수 있다. - -#### 크라우드펀딩 (Fundraiser) - -코스모스가 최초로 생성될 때 아톰 토큰과 검증인의 배분은 코스모스 크라우드세일의 자금제공자들(75%), 사전 자금 제공자들(5%)과 코스모스 주식회사(Cosmos Corp)(20%)로 가게 된다. 그 이후, 아톰 총액 중 1/3 이 본딩된(bonded) 검증인들과 위임자들에게 매년 보상될 것이다. - -이 계획은 변경될 수 있으며 상세내용은 [Crowdfund Plan](https://github.com/cosmos/cosmos/blob/master/PLAN.md) 참조 - -### 검증인수의 제한 (Limitations on the Number of Validators) - -비트코인 등의 작업증명 블록체인들과는 달리, 텐더민트 블록체인은 검증인의 수가 많아질수록 통신의 복잡도가 증가하여 속도가 느려진다. 물론 충분한 검증인들을 통해 블록체인의 전세계 분산, 매우 빠른 이체확인 속도를 제공할 수 있다. 또한 대역폭, 저장공간 및 병렬 컴퓨팅 용량이 증가함에 따라 장래에 더욱 많은 검증인들을 지원할 수 있을 것이다. - -제네시스 시에는 최대 검증인 수가 100 명으로 설정될 것이고, 이 수치는 10 년 동안 13%의 비율로 증가하여 최종적으로는 총 300 명의 검증인을 가지게 될 것이다. - - Year 0: 100 - Year 1: 113 - Year 2: 127 - Year 3: 144 - Year 4: 163 - Year 5: 184 - Year 6: 208 - Year 7: 235 - Year 8: 265 - Year 9: 300 - Year 10: 300 - ... - -### 제네시스 일이후에 검증인되기 (Becoming a Validator After Genesis Day) - -아톰 보유자들은 ‘BondTx 이체’를 서명하여 제출함으로써 검증인이 될 수 있다. 담보로 제공된 아톰 액수는 ‘0’보다 많아야 한다. 현재 검증인 세트의 크기가 허용된 최대 검증인 수보다 많은 경우를 제외하고는 누구라도 언제든지 검증인이 될 수 있다. 만일 검증인의 수가 허용치 이상인 경우, 가장 적은 검증인이 보유한 유효 아톰의 액수보다 더 높은 아톰 액수(위임받은 아톰 포함)를 담보로 제공해야만 한다. 이러한 방식으로 새로운 검증인이 기존 검증인를 대체할 수 있으며, 기존 검증인은 비활성이 되고 모든 아톰과 위임 아톰(delegated atom)은 언본딩 상태(unbonding state)로 돌아간다. - -### 검증인에 대한 처벌 (Penalties for Validators) - -고의든 아니든 검증인이 정해진 프로토콜을 어길 때에는, 처벌이 주어져야 한다. 동일한 높이(height) 및 라운드에서의 이중 서명이나 "prevote-the-lock"(텐더민트 합의 프로토콜의 규칙)의 위반 같은 행위는 증거를 통해 즉시 인정된다. 이 경우, 검증인은 유효한 지위(good standing)를 상실하게 되며, 본딩된 아톰과 ‘지급준비금 풀(reserve pool)’내 토큰의 비례분 즉, 통칭하여 ‘지분(stake)’을 상당수 잃을 것이다. - -때로는 지역 네트워크 단절, 전원 장애나 그 밖의 이유들로 인해 검증인이 단절될 수 있을 것이다. 만일 ‘과거 어느 시점의 ValidatorTimeoutWindow 블록’에서 검증인의 커밋 투표가 이루어지지 않은 횟수가 ValidatorTimeoutMax Absent 횟수 이상인 경우, 해당 검증인은 비활성화 되고 지분의 ‘Validator TimeoutPenalty(디폴트 1%)’만큼 잃게 될 것이다. - -어떤 ‘악의적’ 행위는 블록체인에 명확한 증거를 남기지 않을 수 있다. 이런 경우, 압도적 다수의 합의가 존재한다면, 검증인들이 외부에서 합의한 뒤 악의적인 검증인을 강제로 타임아웃(timeout) 시킬 수 있다. - -‘투표권 ⅓+’이 악의적으로 연합하여 코스모스를 중단시키거나, 이들이 악의적 행동의 증거가 블록체인으로 들어오지 않게 검열하여 삭제하는 경우, 허브는 하드포크를 통한 블록재조정(reorg) 프로포잘로 복구(recover)되어야 한다. - -### 이체 수수료 (Transaction Fees) - -코스모스 허브 검증인들은 아톰 뿐 아니라, 어떠한 유형의 토큰이라도 이체수수료로 받을 수 있다. 각 검증인은, BlockGasLimit 을 초과하지 않는 한, 원하는 어떤 교환비율이든 주관적으로 정할 수 있고 원하는 어떤 이체든 선택할 수 있다. 징수된 수수료는 아래에 명시된 세금들을 제외하고, 매 ValidatorPayoutPeriod(검증인지불기간, 디폴트 1 시간)마다 본딩된 아톰(bonded atoms)에 비례하여 본딩된 주주들(bonded stakeholders)에게 재분배된다. - -징수된 이체수수료 중 ‘지급준비금 세금(Reserve Tax, 디폴트 2%)’은 ‘지금준비금 풀’에 충당되며 이를 통해 ‘지금준비금 풀’을 늘리고 코스모스 네트워크의 보안과 가치를 높이는데 사용될 것이다. 또한 공유세(Commons Tax, 디폴트 3%)는 공유재의 자금으로 충당될 것이다. 이 자금들은 CustodianAddress 로 가게 되고, 거버넌스 시스템의 결정에 따라 분배된다. - -투표권을 다른 검증인들에게 위임하는 아톰 보유자들은 위임 받은 검증인에게 커미션(commission)을 지불한다. 커미션은 각 검증인이 정할 수 있다. - -### 해커에 대한 인센티브 제공 (Incentivizing Hackers) - -코스모스 허브의 보안은 검증인들과 위임자들의 검증인 선택에 달려있다. 취약성 발견 및 조기 보고를 권장하기 위해 코스모스 허브는 해커들이 "이 검증인은 해킹 당했다. 본 주소로 포상금을 보내주기 바란다."라고 알릴 수 있는 ‘ReporthackTx 이체’를 통해 해킹성공 발표를 권장한다. 해킹 즉시, 해당 검증인과 위임자들은 비활성화되고, 이들의 아톰 일부가 ‘HackPunishmentRatio(해킹처벌비율, 디폴트 5%)’만큼 감소되고, 해커는 포상금 주소를 통해 ‘HackRewardRatio(해크보상비율, 디폴트 5%)’만큼 보상받는다. 검증인은 백업 키(backup key)를 사용하여 나머지 아톰을 회수(recover)해야 한다. - -이러한 방법을 이용해 ‘본딩이 완료되지 않은 비귀속(unvested) 아톰’을 전송하려는 악의적 시도를 막기위해, 감별자와 위임자들의 귀속과 비귀속 아톰 비율은 ReportHackTx 전후로 동일하게 유지될 것이다. 해커 포상금은, 존재할 경우, 얼마의 비귀속 아톰을 포함할 것이다. - -### 거버넌스 (Governance Specification) - -코스모스 허브는 소프트웨어 업그레이드와 헌법(규정) 수정뿐 아니라 시스템의 변수 파라미터들과 같은 블록체인의 다양한 변화를 조정하기 위해서 명확한 거버넌스 메커니즘을 가진 분산형 조직에 의해 운영된다. - -모든 검증인들은 모든 프로포잘에 대한 투표책임이 있다. 적시에 투표하지 않는 경우, 해당 검증인은 ‘결석처벌기간(AbsenteeismPenaltyPeriod-디폴트 1 주)’ 동안 자동으로 비활성화된다. - -위임자들(delegators)은 그들이 위임한 검증인의 투표를 자동으로 물려받는다. 이 투표는 수동으로 취소(overriden manually)될 수 있다. 언본딩된(unbonded) 아톰들은 어떤 투표권도 얻지 않는다. - -각 프로포잘은 ‘최소 프로포잘 보증금(MinimumProposalDeposit)’ 토큰을 요구하는데, 이는 아톰을 포함한 하나 이상의 토큰들일 수 있다. 각 프로포잘에 대해 투표자들은 보증금을 사용하기로 투표할 수 있다. 투표자의 절반 이상이 보증금을 사용하기로 선택할 경우, 그 보증금은 지급보증금 풀에 충당된다. 다만, 프로포잘이 스팸이었다거나 기타의 경우라서 소각되는(burned) 아톰은 제외한다. - -각 프로포잘에 대해, 투표자들은 다음의 옵션으로 투표할 수 있다: - -- Yay(찬성) -- YayWithForce(강력히 찬성) -- Nay(반대) -- NayWithForce(강력히 반대) -- Abstain(기권) - -프로포잘의 통과 여부를 결정시에는 과반수의 투표가 요구되지만, 1/3+이 "강력히(with force)" 반대 투표함으로써 과반수의 결정을 거부할 수 있다. 다만 이렇게 과반수가 거부될 경우, 모두가 ‘거부권패널티블록(VetoPenaltyFeeBlocks, 디폴트 1 일 가치의 블록)’을 통해 수수료를 상실함으로 처벌 받고, 과반수 결정을 거부한 당사자는 자신의 아톰 중 ‘거부권패널티아톰(VetoPenaltyAtoms, 디폴트 0.1%)’ 만큼을 추가로 상실한다. - -### 파라미터 변경 프로포잘 (Parameter Change Proposal) - -여기서 정의된 파라미터들 중 어느 것이든 ParameterChangeProposal 의 통과를 통해 변경될 수 있다. - -### 텍스트 프로포잘 (Text Proposal) - -다른 모든 프로포잘들(예. 업그레이드 프로포잘)은 일반적인 TextProposal 을 통해 조정된다. - -## 로드맵 (Roadmap) - -[Plan](https://github.com/cosmos/cosmos/blob/master/PLAN.md) 참조. - -## 관련 연구 (Related Work) - -지난 수십 년 동안 블록체인 합의구조와 확장성 부분에서 많은 혁신이 있었다. 아래에서 중요한 몇 가지를 간략히 개관한다. - -### 합의 시스템 (Consensus Systems) - -#### 고전적 비잔틴 장애 저항 (Classic Byzantine Fault Tolerance) - -악의적인 참여자가 있는 합의는 80 년대 초로 거슬러 올라가는 문제인데, 이때 레슬리 램포트(Leslie Lamport)는 프로세스가 단순한 ‘충돌 장애(crash fault)’와는 대조되는 것으로, 의도된 행위로부터 벗어나는 임의의 프로세스 행위(process behavior)를 가리키는 ‘비잔틴 장애(Byzantine fault)'라는 용어를 만들었다. 초기의 솔루션들은 메시지 지연시간에 상한(upper bound)이 존재하는 동기식 네트워크들을 위한 것이었다. 하지만 실제 사용은 항공기 제어기와 원자시계를 통해 동기화되는 데이터센터 같은 고도로 통제된 환경들로 제한되었다. 임의의 프로세스 행위를 최대 ⅓ 까지 허용할 수 있는 효율적인 ‘부분 동기 합의 알고리즘’으로서 ‘실용적 비잔틴 장애 허용(PBFT: Practical Byzantine Fault Tolerance)’[\[11\]](11)이 도입된 것은 90 년대 말이 되고 나서였다. PBFT 는 표준 알고리즘이 되었고, 많은 파생 변형들을 만들어내었다. 가장 최근에는 IBM 이 하이퍼레저(Hyperledger)에 기여를 위해 만든 변형이 있다. - -PBFT 와 비교할때 텐더민트 합의구조의 중요한 장점은 텐더민트가 단순하고 개선된 기반 구조를 가진다는 것이고, 이 구조 중의 일부는 블록체인 패러다임을 수용한 결과이다. 텐더민트 블록들은 순서대로 커밋되는데, 이것이 PBFT 의 관점 변화(view-changes)와 관련 있는 복잡도와 통신 오버헤드를 제거한다. 코스모스를 포함한 많은 암호화폐에서는, 블록 _N_ 자체가 아직 커밋되지 않았을 때에는 블록 _N+i_(_i >= 1_)의 커밋을 고려할 필요가 없다. 블록 *N*이 코스모스 존에 커밋되지 않은 이유가 대역폭인 경우, _N+i_ 블록들에 대해 대역폭 공유 투표(bandwidth sharing votes)를 사용해도 의미가 없다. 만일 네트워크 분할이나 오프라인 노드들 때문에 블록 *N*이 커밋되지 않은 경우, 블록 *N+i*은 어차피 커밋되지 않는다. - -뿐만 아니라, 블록들 속으로 이체를 배칭(batching)함으로 PBFT 의 체크포인팅(checkpointing) 기법 같은 주기적 다이제스트가 아닌, ‘어플리케이션 상태의 정규 머클 해싱’이 가능하다. 또한 이를 통해, 라이트 클라이언트들을 위한 보다 빠른 증명 가능한 이체 커밋과, 보다 빠른 블록체인 간 통신이 가능하다. - -텐더민트 코어는 PBFT 에 명시된 것 이상의 많은 최적화 사항들과 기능들을 가지고 있다. 예를 들면, 검증인이 제안하는 블록들은 전파 성능을 개선하는 방식으로 부분화되고 머클화(Merkle-ized) 되고 가십화(gossipped)된다(영감은 LibSwift[\[19\]](19) 참조). 또한 텐더민트 코어는 점 대 점(point-to-point) 접속에 관한 어떤 가정도 하지 않으며, P2P 네트워크가 연결되어 있기만 하다면 작동한다. - -#### 비트쉐어 위임 지분 (BitShares delegated stake) - -비트쉐어(BitShares)[\[12\]](12)는 최초의 지분증명(PoS: proof-of-stake) 적용 사례는 아니지만, PoS 블록체인들, 특히 ‘위임(delegated)’ PoS 블록체인의 연구와 채택에 상당한 기여를 했다. 비트쉐어에서 지분 보유자들은 이체명령 및 커밋 책임이 있는 '증인(witnesses)'과 소프트웨어 업데이트와 패러미터 변경 책임이 있는 '델리게이트(delegates)'를 선출한다. 비트쉐어는 이상적인 상태에서 고성능(100k tx/s, 1 초 지연시간)을 달성하기는 하지만, 악의적인 증인들이 아무런 경제적 처벌 없이 블록체인을 분기해 이중지불 공격을 가할 수 있다. 즉 '무보증(Nothing-at-Stake)' 문제를 겪는다. 비트쉐어는 이체들이 최근의 블록-해시들을 참조하게 함으로써 이 문제를 완화하고자 한다. 물론 주주들은 부정행위 증인들을 매일 제거하거나 대체할 수 있다. 하지만 이것이 성공한 이중지불공격에 대한 분명한 처벌은 결코 아니다. - -#### 스텔라 (Stellar) - -리플(Ripple)이 개척한 방식을 토대로, 스텔라(Stellar)[\[13\]](13)는 ‘연합형 비잔틴 합의(Federated Byzantine Agreement)’ 모델을 개선했는데, 여기에서는 합의참여 프로세스에서 ‘전역적으로 알려진 고정된 집합’을 요구하지는 않는다. 오히려 프로세스 노드는 각기 신뢰할 수 있는 프로세스 집합을 구성하는 하나 이상의 '정족수 슬라이스(quorum slices)'를 배포한다. 스텔라에서 '정족수'는 노드들의 집합(set)이며, 적어도 각 노드당 하나 이상의 정족수 슬라이스를 포함하여 합의에 도달하도록 한다. - -스텔라 메커니즘의 보안은 _임의의_ 두 정족수의 교집합이 비공(non-empty)이라는 가정에 의존한다. 또한 노드의 가용성을 위해서는, 정족수 슬라이스들 중 적어도 하나가 완전히 올바른(entirely correct) 노드들로 구성되어야 하며, 신뢰에 관한 중요한 가정 없이는 큰 정족수 슬라이스와 작은 정족수 슬라이스 사용 간에 발생하는 상호관계의 균형유지가 어려울 수 있다. 궁극적으로는 노드들은 충분한 장애허용이 가능한 ‘적절한 정족수 슬라이스’ 또는 ‘온전한 노드들(intact nodes)’을 어떻게든 선택해야 한다. 또한 그런 구성을 보장하는 유일한 전략은 계층적이고, 경계 경로 프로토콜(BGP: Border Gateway Protocol)과도 유사하다. 이는 전역 라우팅 테이블 확립을 위해 인터넷의 최상위 계층 ISP 들에 의해 사용되며, TLS 인증서를 관리하기 위해 브라우저들이 사용하기도 한다. 그러나 두 가지 모두 약한 보안성으로 악명높다. - -스텔라 논문에서 비판한 ‘텐더민트 기반 지분 증명 시스템’들은 이곳에 기술된 토큰 전략을 통해 해명할 수 있다. 이 전략에서는 미래의 수수료 및 보상에 대한 권리인 *아톰*이라는 이름의 새로운 유형의 토큰이 발행된다. ‘텐더민트 기반 지분 증명’은 상대적으로 단순성을 유지하면서도, 충분한 그리고 입증 가능한 보안을 제공한다는 점에서 이점이 있다. - -#### 비트코인 NG (BitcoinNG) - -BitcoinNG 는 블록 크기 확장과 같은 수직 확장성을 제공하는 방법이다. 또한 이러한 확장이 초래하는 부정적 경제 요인들을 최소화하였다. 이러한 개선은 리더 선정(leader election)과 이체 전파를 분리시킴으로 가능하다: 리더들은 우선 ‘마이크로 블록(micro-block)’들에 있는 작업증명(PoW)을 통해 선정되며, 그 이후 새로운 마이크로블록이 발견될 때까지 커밋할 이체내역들을 전파한다. 이러한 방식은 PoW 경쟁을 이기기 위해 소요되는 대역폭 요구량을 줄여준다. 또한 소규모 채굴자들이 더욱 공정하게 경쟁하고 이체가 더 정기적으로 커밋될 수 있도록 한다. - -#### 캐스퍼 (Casper) - -캐스퍼[\[16\]](16)는 이더리움 용으로 제안된 지분증명(PoS) 합의 알고리즘이다. 주요 운용 방식은 '베팅에 의한 합의(consensus-by-bet)'이며, 검증인들은 지금까지 본 다른 베팅들(bets)에 기초해 블록체인에 커밋 될 것으로 생각되는 블록에 반복적으로 베팅하게 되며, 이러한 방식으로 결국 완결성(finality)이 달성된다는 논리를 전제한다. [링크](https://blog.ethereum.org/2015/12/28/understanding-serenity-part-2-casper/). 이러한 ‘합의 베팅’이 캐스퍼 팀의 주요 연구영역인데, 도전이 되는 부분은 베팅 메커니즘을 ‘진화적으로 안정된 전략(evolutionarily stable strategy)’이 되도록 설계해야 한다는 점이다. 텐더민트와 비교할 때 캐스퍼의 강점은 '일관성(consistency)보다 가용성(availability)'을 제공하는 것으로 볼 수 있다. 합의는 투표권의 +⅔ 정족수를 요구하지 않으며 커밋 속도나 구현 복잡도를 희생했다고 볼 수 있다. - -### 수평 스케일링 (Horizontal Scaling) - -#### 인터레저 프로토콜 (Interledger Protocol) - -인터레저 프로토콜(Interledger protocol)[\[14\]](14)은 엄밀히는 확장성 솔루션이 아니다. 느슨하게 연결된 ‘쌍방 관계 네트워크’를 통해 상이한 원장 시스템들 간 ‘애드혹 상호운용성(ad hoc interoperation)’을 제공하는 방식이다. 라이트닝 네트워크(Lightning Network)의 경우처럼, ILP 는 지불을 용이하게 하는 프로토콜인데, 특히 서로 다른 유형의 원장들 간 지불에 초점을 맞추며 ‘아톰 이체 메커니즘(atomic transaction mechanism)’을 확장하여 ‘해시 잠금(hash-locks)’과 ‘공증인 정족수(quorum of notaries)’를 포함하로독 했으며, 이를 ‘아톰 전송 프로트콜(Atomic Transport Protocol)’로 칭한다. ‘원장 간 이체의 원자성(atomicity)’을 확보하기 위한 이러한 메커니즘은 텐더민트의 ‘라이트 클라이언트 SPV’ 작동방식과도 유사하다. 하단에서 ILP 와 코스모스/IBC 를 비교해본다. - -1. ILP 의 커넥터(connector) 공증인들은 구성원(membership) 변경을 지원하지 않으며 공증인들 간 유연한 가중치 부여를 지원하지 않는다. 반면에 IBC 는 블록체인 전용으로 설계되었고, 검증인들이 상이한 가중치를 가질 수 있으며 블록체인을 통해 구성원들의 변경이 가능하다. - -2. 라이트닝 네트워크나 ILP 에서는 지불 수신자가 송신자에게 ‘확인’을 되돌려 보내기 위해 반드시 온라인 상태여야 한다. IBC 를 통한 토큰 전송에서는, 수신자가 아니라, 수신자 블록체인의 검증인 세트가 ‘확인’을 제공할 책임이 있다. - -3. 가장 근본적인 차이는 ILP 커넥터들은 지불에 대한 책임을 지거나 권한 상태를 유지하고 있지 않은 반면에, 코스모스에서는 허브의 검증인들이 IBC 토큰 전송과 각 존이 가진 토큰 총액에 대한 권한을 가진다는 점이다(그러나 존 내 각 계정이 보유한 토큰 금액에 대한 권한은 없다). 이는 존에서 존으로 비대칭 토큰 전송을 안전하게 실행하기 위한 근본적 혁신이다. - -4. ILP 에서 원장 간 지불을 하기 위해서는 거래소 오더북(exchange orderbook)의 지원이 필요한데, 이는 하나의 원장에서 다른 원장으로의 ‘코인 비대칭 전송’이 없고 ‘가치나 시장 등가물(market equivalents)’의 전송만 있기 때문이다. - -#### 사이드체인 (Sidechains) - -사이드체인(sidechains)[\[15\]](15)은 비트코인 블록체인에 '페깅(pegged)'된 ‘대안 블록체인’을 통해 비트코인 네트워크를 확장하고자 하는 시도이다. 사이드체인은 비트코인이 비트코인 블록체인으로부터 사이드체인으로 효과적으로 이동할 수 있게 하고 사이드체인에서 각 체인의 특징을 이용한 실험들을 가능하게 한다. 코스모스 허브와 마찬가지로, 사이드체인과 비트코인은 상호 간 라이트 클라이언트 역할을 하며 코인 전송 시점을 결정하기 위해 SPV 증명을 사용한다. 물론 비트코인은 작업증명을 사용하기 때문에 비트코인 중심의 사이드체인들은 작업증명 합의 메커니즘으로부터 발생하는 여러 문제들과 리스크를 갖는다. 이는 ‘비트코인 극단주의자(Bitcoin-maximalist)’적 솔루션이며, 코스모스처럼 자체적으로 다양한 토큰들과 존 간 네트워크 위상(inter-zone network topology)을 지원하지는 않는다. 하지만, ‘양방향 페그(two way peg)’의 핵심 메커니즘 자체는 코스모스 네트워크의 방식과 원칙적으로 동일하다. - -#### 이더리움 확장성 노력 (Ethereum Scalability Efforts) - -이더리움은 확장성 확보를 위해 ‘이더리움 블록체인 상태’를 샤딩(sharding)하기 위한 여러 전략들을 연구 중이다. 현재의 이더리움 가상 머신(EVM)를 통해 ‘공유 상태 공간(shared state space)’에 ‘대한 추상적 계층(abstraction layer)’을 유지하는 방식이다. 또한 다수의 연구들이 진행되고 있다.[\[18\]](18)[\[22\]](22) - -#### 코스모스 vs 이더리움 2.0 Mauve (Cosmos vs Ethereum 2.0 Mauve) - -코스모스와 이더리움 2.0 Mauve[\[22\]](22)의 설계 목표에는 차이가 있다. - -- 코스모스가 토큰들에 대한 것이라면 Mauve 는 일반 계산(general computation)의 스케일링에 관한 것이다. - -- 코스모스는 EVM 에 구속되지 않으며, 심지어는 서로 다른 VM 들이 상호 운용될 수 있다. - -- 코스모스는 존의 검증 책임자를 존의 생성자가 결정하도록 한다. - -- (거버넌스 시스템의 결정과 상충되지만 않는다면) 누구든지 코스모스에서 새 존을 시작할 수 있다. - -- 허브는 존 실패(zone failures)를 격리시키며, 이를 통해 ‘전역 토큰 불변성(global token invariants)’을 보증한다. - -### 일반 스케일링 (General Scaling) - -#### 라이트닝 네트워크 (Lightning Network) - -라이트닝 네트워크는 비트코인 블록체인(그리고 그 밖의 퍼블릭 블록체인들)의 상위 계층에서 운용되도록 제안된 토큰 전송 네트워크로, 합의원장(consensus ledger) 외부의 대다수 이체들을 소위 ‘지불채널(payment channels)’로 이동시켜서 이체처리량(throughput)을 획기적으로 개선시킨다. 온 체인(on-chain) 암호화폐 스크립트를 통해 당사자들이 쌍무 상태기반 계약(bilateral stateful contracts)을 체결할 수 있도록 한다. 계약들의 상태는 디지털 서명에 의해 업데이트 되며, 또한 ‘크로스 체인 아토믹 스왑(cross-chain atomic swap)’를 통해 최초에 설정된 방식에 따라 합당한 증명을 블록체인에 전파함으로 계약이 마감된다. 다수의 당사자와 함께 지불 채널을 개방함으로, 라이트닝 네트워크의 참여자들은 당사자들이 지불을 라우팅하는 ‘포컬포인트(focal point)’의 역할을 할 수 있다. 또한 이러한 지불 채널에 실제 자본을 고정시킴으로 완전히 연결된 지불 채널을 개설하는 것도 가능하다. - -라이트닝 네트워크는 다수의 블록체인들에 걸쳐 확장되면서 교환시장을 통해 *가치(value)*를 전송하도록 하지만, 하나의 블록체인에서 다른 블록체인으로 *토큰(token)*을 비대칭적으로 전송하는 것은 불가능하다. 이와 관련된 코스모스 네트워크의 주된 이점은 그러한 토큰의 직접 전송을 지원한다는 것이다. 물론, 비용 절감과 프라이버시 차원에서 토큰 전송 메커니즘이 지불 채널들과 라이트닝 네트워크와 함께 적용되기를 기대한다. - -#### 세그위트 (Segregated Witness) - -세그위트(Segregated Witness)는 블록 당 이체처리량을 2-3 배 가량 증가시키는 것을 목적으로 하며, 동시에 신규 노드들이 더욱 빠르게 블록 동기화(block syncing)를 하도록 돕는 비트코인 개선 제안이다([참조](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)). 이 솔루션은 비트코인의 현재 프로토콜 내에서 작동하면서 소프트 포크 업그레이드(soft-fork upgrade)를 허용하는 방식이다. 따라서, 이전의 소프트웨어 버전을 가진 클라이언트들도 업그레이드를 받아 정상적으로 기능할 수 있다. 텐더민트의 경우, 새로운 프로토콜을 만드는데 아무런 제약이 없기 때문에 확장성에 대한 새로운 우선순위를 가진다. 주로 텐더민트는 채굴 대신 암호 서명에 기반한 ‘BFT 라운드 로빈 알고리즘(BFT round-robin algorithm)’을 사용한다. 이를 통해, 다중 병렬 블록체인을 이용한 수평 스케일링을 가능하게 하면서도, 보다 정기적이고 자주 발생하는 블록 커밋에는 수직 스케일링을 적용할 수도 있다. - -<hr/> - -## 부 록 (Appendix) - -### 포크 책임 (Fork Accountability) - -잘 설계된 합의 프로토콜이라면 허용 용량(tolerance capacity)이 초과되거나 합의가 실패할 경우에도 문제가 없어야 한다. 이는 ‘비잔틴 행동’에 상당한 금전적 보상이 있을 수 있는 경제시스템에서 특히 중요하다. 그러한 보장 중 가장 중요한 것이 ‘_포크 책임(fork-accountability)_’인데, 포킹과 같은 합의실패를 초래한 프로세스들이 프로토콜 규칙이나 법적 체계(가능하다면)에 의해 식별되고 처벌받을 수 있다. 법 체계를 신뢰할 수 없거나 적용하기에 과도한 비용이 들 경우, 검증인들이 담보 보증(security deposits)을 내고 참여하도록 하고 악영향을 주는 행위 시 해당 담보를 차감하거나 강제로 환수함으로 처벌할 수 있다[\[10\]](10). - -‘포크 책임’에서 다루는 것은 비트코인에서처럼 ‘네트워크 비동시성’과 ‘부분적 해시충돌’ 특성으로 인해 일어나는 정상적 분기와는 큰 차이가 있다. 많은 경우, 비동시성 때문에 악의적 포킹을 가려내는 것이 거의 불가능하기 때문에 비트코인의 경우 채굴자들이 포킹을 시도하다가 고아블록이 되어버리는 기회비용을 제외하고는 특별히 ‘포크 책임’을 물게하는 것이 어렵다. - -### 텐더민트 합의 (Tendermint Consensus) - -투표 단계들은 *프리보트(PreVote)*와 *프리커밋(PreCommit)*으로 나뉜다. 투표는 특정 블록이나 ‘_무효(Nil)_’를 위해 행사될 수 있다. 동일 라운드에서 단일 블록에 대한 +⅔ PreVote 집합을 *폴카(Polka)*라고 부르며, 동일 라운드에서의 단일 블록에 대한 +⅔ PreCommit 집합을 *커밋(Commit)*이라고 부른다. 만일 동일 라운드에서 ‘무효(Nil)’에 +⅔ PreCommit 상태라면, 다음 라운드로 이동한다. - -결함 있는 리더들을 검출하고 무시하기 위해 엄격한 결정성(determinism)을 사용하다가 오히려 약한 동시성(synchrony)을 초래할 수 있다. 따라서 검증인들은 무효(Nil)를 Prevote 하기 전에, 일정 시간(*TimeoutPropose)*을 기다리게 되며 이 TimeoutPropose 값은 매 라운드마다 점점 증가한다. 검증인이 네트워크의 +⅔ 로부터 전파받을 때에만 단 한번 진행이 되므로, 라운드의 나머지 부분 진행은 완전히 비동시적이다. 실제로, 약한 동시성 가정( weak synchrony assumption)을 계속해서 좌절시키고 결국 블록 커밋을 위한 합의를 실패시키기 위해서는 극단적으로 강한 공격자가 필요하다. 또한 각 검증인에게 서로 다른 TimeoutPropose 랜덤값을 적용한다면, 공격은 더욱 어려워진다. - -‘추가 제약조건 집합’, 즉 ‘잠금 규칙(Locking Rules)’은 네트워크가 각 높이에서 단 하나의 블록만을 커밋하도록 보장한다. 특정한 높이에서 두 개 이상의 블록을 커밋되게 하려는 시도는 모두 발각될 수 있다. 첫째로, 블록에 대한 프리커밋(PreCommit)은 해당 블록에 대한 폴카의 형태로 정당화(justification)되어야 한다. 만일 검증인이 이미* R_1* 라운드에서 블록을 프리커밋했다면, 이는 해당 블록에 로킹*(locked)*되며, _R_2_ 라운드의 새로운 프리커밋은 반드시 *R_1 < R_polka <= R_2*인 ‘R_polka 라운드’에서 발생해야한다. 둘째로, 검증인들은 자신들이 로킹되어 있는 블록을 제안(Propose)하거나 아니면 사전투표(PreVote)하거나 또는 둘을 함께 해야한다. 이를 통해 검증인은 충분한 증거 없이 프리커밋하지 못하며, 이미 프리커밋한 검증인의 경우 다른 블록을 동시에 프리커밋할 수 없게 된다. 이렇게 합의 알고리즘의 안전성(safety)과 라이브성(liveness)을 보장하게 된다. - -프로토콜의 전체 세부내용은 [여기](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm)를 참조 - -### 텐더민트 라이트 클라이언트 (Tendermint Light Clients) - -대안 체인(포크)의 존재 덕분에 본딩된(bonded) 지분을 ⅓+이 대폭 삭감할(slashed) 수 있기 때문에, 텐더민트 PoS 에서는 모든 블록 헤더들을 동기화(sync)할 필요가 없다. 물론 이러한 삭감을 위해서는 누군가가 포킹의 증거를 공유해야 하기 때문에, 라이트 클라이언트는 전파받는 모든 블록해시 커밋을 저장해야 한다. 뿐만 아니라, 라이트 클라이언트들은 ‘검증인 세트의 변경’과 주기적으로 동기화하여 [장기 공격(long range attacks)](#preventing-long-range-attacks)을 피할 수 있을 것이다(물론 다른 방법도 적용가능). - -이더리움과 유사한 의도로, 텐더민트는 애플리케이션들이 각 블록에 ‘전역 머클 루트 해시(global Merkle root hash)’를 임베딩(embed)하도록 하고, 계정 잔고, 컨트랙트내 저장 값, UTXO 등 각 어플리케이션에 적합한 쉽게 검증이 가능한 ‘상태 쿼리(state queries)’를 이용하도록 한다. - -### 장기 공격 방지 (Preventing Long Range Attacks) - -‘충분한 회복력(resilient)의 전파 네트워크 집합’과 ‘정적(static) 검증인 세트’가 있다면, 블록체인의 모든 포킹이 검출될 수 있으며 문제가 되는 검증인들의 보증금을 대폭 삭감시킬 수 있다. 2014 년 초에 비탈릭 뷰터린(Vitalik Buterin)은 처음 지분증명 암호화폐들의 ‘무처벌(nothing-at-stake)’ 문제에 대한 해결책을 제시한다([관련 연구](#related-work) 참조). 그러나 검증인 세트들이 항상 고정되어 있는 것이 아니기 때문에 오랜 기간에 걸쳐 원래의 검증인들은 모두 언본딩 될 수 있고(may all become unbonded) 묶어둔 보증금이 사라지면서, 어떤 비용도 치르지 않고 제네시스 블록으로부터 새로운 체인을 자유로이 생성할 수 있게 된다. 이 공격은 단기 공격(Short Range Attack)과 대조되는 개념으로 ‘장기 공격(Long Range Attack)’으로 알려지게 되었다. 텐더민트 합의와 같은 ‘포크 책임 BFT 알고리즘(folk-accountable BFT algorithm)’이 존재한다면 현재 본딩된 검증인들이 포크를 초래하는 단기공격은 처벌이 가능하다. 반면 장기 공격은 지분증명 방식에 치명적인 공격으로 간주된다. - -다행히 ‘장기공격(LRA)’을 부분적으로 방지하는 것이 가능하다. 첫째로, 검증인이 보증금을 언본딩하여 보증금을 회수하고 동시에 더이상의 합의참여 수수료를 포기하기 위해서는 정해진 일정 기간, 즉 ‘언본딩 기간(unbonding period)’을 채워야 한다. 그 기간은 수주 또는 수개월이 된다. 둘째로, 라이트 클라이언트는 최초로 네트워크에 연결될 때 신뢰할 수 있는 한개 이상의 출처를 통해 네트워크의 최근 블록해시를 검증해야 한다. 이러한 조건을 ‘약한 주체성(weak subjectivity)’으로 부르기도 한다. 마지막으로, 보안성을 유지하기 위해서 적어도 매 ‘언본딩 기간’을 주기로 ‘최종 검증인 세트’와 동기화되어야 한다. 이를 통해, 라이트 클라이언트는 검증인이 보증금을 빼내고 ‘무보증 상태(Nothing at Stake)’가 되었는지 여부를 파악할 수 있게 된다. 이를 파악하지 못한다면, 검증인은 최초 본딩이 시작된 블록으로 돌아가 새로우 블록들을 다시 생성함으로 장기공격을 감행할 수 있다(물론 이를 위해서는 검증인이 충분히 많은 초기 개인키를 가지고 있어야 함). - -이러한 방식의 LRA 대응 방안은 기존 ‘작업증명(Proof-of-Work)’ 방식의 보안 기법에 대한 완전한 분해정비를 필요로 한다. ‘작업증명’에서는, 라이트 클라이언트가 언제든 전체 블록헤더의 작업증명을 처리하기만 한다면 신뢰할 수 있는 제네시스 블록을 통해 최신 블록체인을 동기화할 수 있다. 그러나 LRA 에 대응하기 위해서는, 라이트 클라이언트가 정기적으로 온라인 상태가 되어 검증인 세트를 추적해야하며, 최초 온라인이 되었을 때 반드시 신뢰할 만한 출처를 통해 네트워크에서 제공하는 정보의 진실성을 확인해야만 한다. 물론 신뢰할만한 출처를 이용하는 방법은 비트코인에서도 동일한데, 프로토콜이나 소프트웨어를 반드시 신뢰할 수 있는 출처에서 얻어야 하기 때문이다. - -LRA 를 방지하는 상기의 방법은, 검증인들과 텐더민트 기반 블록체인의 완전 노드들에 적합하다. 이 노드들은 네트워크에 계속 연결되어 있기 때문이다. 또한 이 방법은 네트워크에 자주 연결될 수 있는 라이트 클라이언트들에도 적합하다. 하지만 라이트 클라이언트들이 자주 연결될 수 없는 경우, 다른 방법이 사용될 수 있다. 검증인이 아닌 토큰 보유자들이 상당히 긴 기간동안 자신의 토큰을 담보로 제공하는 것이다. 그리고 라이트 클라이언트들에게 이차적인 방법으로 최근과 이전의 블록해시 값을 전달하는 것이다. 이러한 토큰들이 블록체인 합의와 관련된 보안에는 영향을 미치지 않으나 라이트 클라이언트에게는 강력한 보장을 제공할 수 있다. 역사적 블록-해시 질의가 이더리움에서 지원될 경우, 누구든지 특별 설계된 스마트 컨트랙트에서 자신의 토큰을 본딩하고 지불을 위한 인증 서비스(attestation services for pay)를 제공하여 라이트 클라이언트 LRA 보안 시장을 효과적으로 창출할 수 있을 것이다. - -### 포크 및 검열 공격 극복 (Overcoming Forks and Censorship Attacks) - -블록 커밋의 정의로 인해, ⅓+ 투표권 연합은 오프라인이 되거나 투표전파를 거부함으로 블록체인을 중단시킬 수 있다. 그러한 연합을 통해 특정한 이체를 포함한 블록을 검열하여 탈락시킬 수도 있으며, 이 경우 상당한 양의 프로포잘이 거부되고 블록커밋 속도를 늦추어 블록체인의 효용과 가치를 낮출수도 있다. 또한 연합은 소량의 투표만을 전파하여 블록체인의 블록커밋 속도를 서서히 늦출 수도 있다. 결정적으로 이들은 이중서명이나 잠금규정을 지키지 않음으로 블록체인을 분기(포킹)시킬 수도 있다. - -전역적 능동 공격자(global active adversary)가 관여할 경우, 네트워크를 분할시키고 다른 이가 책임이 있는 것처럼 보이게 할 수도 있다. 이는 텐더민트만의 문제는 아니며 네트워크 상에 능동 공격자가 존재하는 모든 합의 프로토콜이 가진 한계이다. - -이러한 유형의 공격이 가능해지려면, 발리데이터 부분집합(a subset of the validators)이 합동하여 외부수단을 이용해 포킹 목적의 블록재조정 프로포잘에 서명해야하고, 초기 발리데이터 부분집합도 이에 서명해야한다. 클라이언트들은 블록재조정 프로포잘의 서명을 유심히 검증하고, 이를 근거로 판단하거나 그 결정을 최종사용자에게 넘길 수 있다. - -어떤 ‘비동시성 비잔틴 장애 저항 알고리즘(non-synchronous Byzantine fault-tolerant algorithm)’도 투표권의 ⅓+이 부정직할 경우, 합의에 도달할 수 없다. 하지만, 포크의 경우 투표권의 ⅓+이 이미 이중 서명이나 잠금 변경(lock-changing)에 의해 부정직한 것으로 가정한다. 따라서 블록재조정 프로포잘(reorg-proposal)에 서명하는 것은 어떤 비동시성 프로토콜에서도(즉, 자동적으로 그리고 기반 네트워크의 신뢰성에 관한 가정없이는) 해결할 수 없는 조정 문제이다. 현재로서는 ‘블록재조정 프로포잘 조정(reorg-proposal coordination)’ 문제를 인터넷 매체 상에서 일어나는 인간들의 사회적 합의에 맡기고 있다. 상충되는 두 블록재조정 프로포잘에 서명하는 것을 방지하기 위해, 검증인들은 서명에 앞서 남은 네트워크 분할이 없도록 주의해야 한다. - -외부의 조정 수단 및 프로토콜이 강인하다면, 네트워크분기(포크)가 검열 공격보다는 덜 치명적이다. - -⅓ 비잔틴 투표권을 요구하는 포크 및 검열 외에, +⅔ 투표권의 연합이 임의의 무효 상태를 커밋할 수도 있다. 이는 모든 BFT 합의 시스템의 특징이다. 쉽게 검증 가능한 포크가 생성되는 이중서명과는 달리, 무효 상태 커밋(commitment of an invalid state)을 검증하기 위해서는 발리데이터가 아닌 피어들(non-validating peers)도 전체 블록들을 검증해야한다. 이는 피어들이 상태의 지역 사본(local copy)을 가지고 각 이체를 실행하며, 상태 루트(state root)를 독립적으로 계산한다는 것을 의미한다. 또한 무효상태커밋이 검출되면, 사회적 합의만이 이를 처리하는 유일한 방법이다. 예를 들어, (2013 년 3 월처럼) 소프트웨어 버그로 인한 분기이든, 또는 (2015 년 7 월처럼) 채굴자들의 비잔틴 행동으로 인한 무효 상태 커밋이든 비트코인이 실패한 상황들에서, 비즈니스, 개발자, 채굴자 및 그 밖의 조직들의 잘 연결된 커뮤니티는 네트워크 회복을 위해서 참여자들의 무엇을 해야하는지에 대한 사회적 합의를 확립했다. 텐더민트의 경우, 블록체인의 검증인들이 식별될 수 있을 것으로 예상되기 때문에, 필요한 경우, 무효 상태의 커밋을 법률이나 어떤 외부 관할권을 통해 처벌하는 것까지도 가능할 수 있다. - -### TMSP 명세 (TMSP specification) - -TMSP 는 코어에서 애플리케이션으로 전달되는 3 가지 주요 메시지 유형으로 구성된다. 애플리케이션은 대응하는 응답 메시지로 응답한다. - -AppendTx 메시지는 애플리케이션의 핵심 작업수단이다. 블록체인에서의 이체는 이 메시지와 함께 전달된다. 애플리케이션은 AppendTx 메시지와 함께 수신된 각 이체를 현재의 상태, 애플리케이션 프로토콜, 이체의 암호학적 요건 등과 비교해서 검증한다. 이후, 검증된 이체는 값을 키-값 저장장치(key values store)으로 결합하거나 UTXO 데이터베이스를 업데이트하여 애플리케이션 상태를 업데이트해야 한다. - -CheckTx 메시지는 AppendTx 와 유사하지만 이체 검증에만 사용된다. 텐더민트 코어의 mempool(메모리 풀)은 CheckTx 로 이체의 유효성을 검사하고 유효한 이체만 피어들에 전파한다. 애플리케이션들은 이체의 증가 논스 (incrementing nonce)를 검사하고 논스가 오래된 경우, CheckTx 에 오류를 반환할 수도 있다. - -Commit 메시지는 다음 블록 헤더에 포함될 현재 애플리케이션 상태에 대한 암호학적 커밋(cryptographic commitment)을 계산하기 위해 사용된다. 이를 통해 몇가지를 얻을 수 있다. 해당 상태 업데이트에서 불일치들이 포크의 형태로 나타나게 된다. 또한 머클-해시 증명들이 블록-해시와의 비교를 통해 검증될 수 있고 블록-해시는 (투표권에 의한) 검증인 정족수에 의해 서명되기 때문에, 단순한 방식으로 안전한 라이트 클라이언트 개발하는데 도움이 된다. - -추가적 TMSP 메시지를 통해 애플리케이션이 검증인 세트를 추적(keep track of) 및 변경하고, 높이와 커밋 투표 같은 블록 정보를 수신할 수 있다. - -TMSP 요구/응답(TMSP requests/responses)은 간단한 Protobuf 메시지들이다. [스키마 파일(schema file)](https://github.com/tendermint/abci/blob/master/types/types.proto) 확인 - -##### AppendTx - -- **Arguments**: - - `Data ([]byte)`: The request transaction bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: Result bytes, if any - - `Log (string)`: Debug or error message -- **사용법**:<br/> - 이체를 덧붙이고 실행한다. 이체가 유효할 경우, CodeType.OK 를 반환한다. - -##### CheckTx - -- **Arguments**: - - `Data ([]byte)`: The request transaction bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: Result bytes, if any - - `Log (string)`: Debug or error message -- **사용법**:<br/> - 이체를 검증한다. 이 메시지가 상태를 변경(mutate)해서는 안 된다. 이체들은 mempool 계층의 피어들에게 전파되기 전, CheckTx 를 통해 먼저 실행된다. 동일 블록 내 이체의 발생 순서를 고려하기 위해 CheckTx 를 semi-stateful(준-상태기반)로 만들고 Commit 또는 BeginBlock 시에 상태를 클리어(clear) 할 수 있다. - -##### 커밋 (Commit) - -- **Returns**: - - `Data ([]byte)`: The Merkle root hash - - `Log (string)`: Debug or error message -- **사용법**:<br/> - 애플리케이션 상태의 머클 루트 해시를 반환한다. - -##### Query - -- **Arguments**: - - `Data ([]byte)`: The query request bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: The query response bytes - - `Log (string)`: Debug or error message - -##### Flush - -- **사용법**:<br/> - 응답 대기행렬(response queue)을 플러시(flush)한다. types.Application 을 구현하는 애플리케이션들은 이 메시지를 구현할 필요가 없다--프로젝트에 의해 처리되기 때문이다. - -##### Info - -- **Returns**: - - `Data ([]byte)`: The info bytes -- **사용법**:<br/> - 애플리케이션 상태에 관한 정보를 반환한다. 애플리케이션 특정적이다. - -##### SetOption - -- **Arguments**: - - `Key (string)`: Key to set - - `Value (string)`: Value to set for key -- **Returns**: - - `Log (string)`: Debug or error message -- **사용법**:<br/> - 애플리케이션 옵션을 설정한다. 예를 들어, mempool 연결을 위해서는 Key='mode', Value='mempool', 또는 합의 연결을 위해서는 Key='mode', Value='consensus'. 다른 옵션들은 각 애플리케이션마다 다르다. - -##### InitChain - -- **Arguments**: - - `Validators ([]Validator)`: Initial genesis-validators -- **사용법**:<br/> - 제네시스 시, 1 회 호출됨. - -##### BeginBlock - -- **Arguments**: - - `Height (uint64)`: The block height that is starting -- **사용법**:<br/> - 새 블록의 시작을 알린다. 모든 AppendTx 에 앞서 호출됨. - -##### EndBlock - -- **Arguments**: - - `Height (uint64)`: The block height that ended -- **Returns**: - - `Validators ([]Validator)`: Changed validators with new voting powers (0 - to remove) -- **사용법**:<br/> - 블록의 끝을 알린다. 이체 후, 각 커밋에 앞서 호출됨. - -상세한 내용은 [TMSP 리포지토리(TMSP repository)](https://github.com/tendermint/abci) 참조. - -### IBC 패킷 전송 확인응답 (IBC Packet Delivery Acknowledgement) - -발신자가 수신 체인의 패킷전송 확인응답을 원할 여러 가지 경우가 존재한다. 예를 들어 장애가 있을 경우, 송신자는 수신 체인의 상태를 모를 수 있다. 또는 송신자는 (MaxHeight 패킷 필드로) 패킷에 타임아웃을 부여하기를 원하는 반면, 수신 체인이 갑작스런 수신 패킷 수 급증에 의한 서비스 거부(denial-of-service) 공격을 받을 수도 있다. - -이런 경우, 송신자는 초기 패킷 상태를 AckPending 으로 설정하여 전송 확인응답을 요구할 수 있다. 그러면 앱 머클 해시에 abbreviatedIBCPacket 을 포함하여 전송을 확인해 주는 것이 수신 체인의 책임이다. - -![Figure of Zone1, Zone2, and Hub IBC with acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack.png) - -먼저, 'Zone 1'에 IBCPacket 이 존재함을 증명하는 '허브'가 있다. 그리고 이 허브 위에 IBCBlockCommit 과 IBCPacketTx 가 포스팅된다. 예를 들어 IBCPacketTx 는 다음과 같은 값을 갖는다: - -- `FromChainID`: "Zone1" -- `FromBlockHeight`: 100 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 (say) - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 (say "Hub" is currently at height 300) - - `Payload`: <The bytes of a "coin" payload> - -다음으로, '허브'에 IBCPacket 이 존재함을 증명하는 'Zone 2' 위에 IBCBlockCommit 과 IBCPacketTx 가 포스팅된다. 예를 들면, IBCPacketTx 는 다음과 같다: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 300 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 - - `Payload`: <The same bytes of a "coin" payload> - -그 다음, 'Zone 2'는 앱-해시(app-hash)에 새로운 상태의 AckSent 를 보이는 생략형 패킷을 반드시 포함해야 한다. 생략형 IBCPacket 이 ‘Zone 2' 위에 존재함을 증명하는 '허브' 위에 IBCBlockCommit 와 IBCPacketTx 가 다시 포스팅된다. 예를 들면 IBCPacketTx 는 다음과 같다: - -- `FromChainID`: "Zone2" -- `FromBlockHeight`: 400 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckSent` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <The hash bytes of the same "coin" payload> - -끝으로, '허브'는 패킷의 상태를 AckPending 에서 AckReceived 로 업데이트 해야 한다. 이 새로이 완결된 상태의 증거가 'Zone 2'로 되돌아간다. 예를 들면, IBCPacketTx 는 다음과 같은 값을 갖는다: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 301 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckReceived` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <The hash bytes of the same "coin" payload> - -한편, 'Zone 1'은 ‘코인’패킷 전송의 실패가 '허브' 상에서 증명되지 않는 한, 성공적으로 전송될 것이라고 가정할 것이다. 위의 예에서, '허브'는 ‘블록 350’를 통해 'Zone 2'의 AckSent 상태를 수신하지 않는다면, 상태를 타임아웃(Timeout)으로 자동 설정했을 것이다. 이 타임아웃 증거가 'Zone 1'에 다시 포스팅 될 수 있고, 모든 토큰은 반환될 수 있다. - -![Figure of Zone1, Zone2, and Hub IBC with acknowledgement and timeout](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack_timeout.png) - -### 머클 트리와 증명 명세 (Merkle Tree & Proof Specification) - -두 가지의 머클 트리 유형이 텐더민트/코스모스 생태계에서 지원된다: 단순 트리(Simple Tree)와 IAVL+ 트리. - -#### 단순 트리 (Simple Tree) - -단순트리는 요소들(elements)의 정적 리스트(static list)를 위한 머클 트리이다. 항목의 수가 2 의 거듭제곱이 아닐 경우, 잎들이 서로 다른 수준에 위치할 수 있다. 단순 트리는 트리의 양측면을 동일한 높이로 유지하고자 하지만, 좌측이 더 클 수도 있다. 이 머클 트리는 블록의 이체들을 그리고 애플리케이션 상태 루트의 최상위 요소들을 머클화 하기 위해 사용된다. - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - - 7요소의 단순트리 - -#### IAVL+ Tree - -IAVL+ 데이터 구조의 목적은 애플리케이션 상태의 키-값 쌍들에 영구 저장(persistent storage)을 제공하는 것이다. 그렇게 하여 결정론적 머클 루트 해시를 효율적으로 계산한다. 트리는 [AVL 알고리즘](https://en.wikipedia.org/wiki/AVL_tree)의 변형(variant)을 사용하여 밸런싱되며(balancing), 모든 연산(operations)은 O(log(n))이다. - -AVL 트리에서는 임의 노드의 2 개 ‘자식 서브트리(child subtree)’의 높이가 최대 1 차이가 난다. 업데이트 시, 이 조건이 위반될 때마다 트리는 이전 트리의 비수정 노드들을 가리키는 O(log(n))의 새 노드들을 만들어서 다시 균형을 잡는다. 기존 AVL 알고리즘에서는 내부 노드들이 키-값 쌍들도 보유할 수 있다. AVL+ 알고리즘(플러스에 주의한다)은 잎 노드 상의 모든 값을 유지하기 위해 AVL 알고리즘을 수정하며, 가지 노드들만 사용하여 키를 저장한다. 이를 통해 알고리즘을 단순화하고, 머클 해시 트레일(merkle hash trail)을 짧게 유지한다. - -AVL+ 트리는 이더리움의 [패트리샤 트라이(Patricia tries)](https://en.wikipedia.org/wiki/Radix_tree)와 유사하다. 장단점이 존재한다. 키들은 IAVL+ 트리에 삽입되기 전에 해싱될 필요가 없고, 따라서 키 공간(key space)에서의 빠른 순서반복(ordered iteration)을 제공한다. 로직의 구현이 간편하고 내부 노드(inner nodes)와 잎 노드(leaf nodes)만 필요로 한다. 머클 증명은 일반적으로 짧고 균형 잡힌 이진 트리이다. 반면에 IAVL+ 트리의 머클 루트는 업데이트의 순서(order of updates)에 의존한다. - -이진 변형(binary variant) 사용이 가능해지면, 이더리움의 패트리샤 트라이 같은 효율적 머클 트리들을 추가로 지원할 것이다. - -### 이체 유형 (Transaction Types) - -일반적으로, 이체들은 TMSP 인터페이스를 통해 코스모스 허브 애플리케이션으로 흘러간다. - -코스모스 허브는 앞으로 SendTx, BondTx, UnbondTx, ReportHackTx, SlashTx, BurnAtomTx, ProposalCreateTx, ProposalVoteTx 등을 포함한 많은 주요 이체 유형들(primary transaction types)을 추가할 것이고 문서화할 것이다. 여기서는 IBC 의 두 주요 이체 유형인 IBCBlockCommitTx 와 IBCPacketTx 에 대해 설명한다. - -#### IBCBlockCommitTx - -IBCBlockCommitTx 이체는 다음으로 구성된다: - -- `ChainID (string)`: The ID of the blockchain -- `BlockHash ([]byte)`: The block-hash bytes, the Merkle root which includes the - app-hash -- `BlockPartsHeader (PartSetHeader)`: The block part-set header bytes, only - needed to verify vote signatures -- `BlockHeight (int)`: The height of the commit -- `BlockRound (int)`: The round of the commit -- `Commit ([]Vote)`: The +⅔ Tendermint `Precommit` votes that comprise a block - commit -- `ValidatorsHash ([]byte)`: A Merkle-tree root hash of the new validator set -- `ValidatorsHashProof (SimpleProof)`: A SimpleTree Merkle-proof for proving the - `ValidatorsHash` against the `BlockHash` -- `AppHash ([]byte)`: A IAVLTree Merkle-tree root hash of the application state -- `AppHashProof (SimpleProof)`: A SimpleTree Merkle-proof for proving the - `AppHash` against the `BlockHash` - -#### IBCPacketTx - -IBCPacket 은 다음으로 구성된다: - -- `Header (IBCPacketHeader)`: The packet header -- `Payload ([]byte)`: The bytes of the packet payload. _Optional_ -- `PayloadHash ([]byte)`: The hash for the bytes of the packet. _Optional_ - -Payload 또는 PayloadHash 가 반드시 존재해야 한다. IBCPacket 의 해시는 Header 와 Payload 의 단순 머클 루트이다. 전체 페이로드(full payload)가 없는 IBCPacket 은 _생략형 패킷_(_abbreviated packet_)이라고 부른다. - -IBCPacketHeader 는 다음으로 구성된다. - -- `SrcChainID (string)`: The source blockchain ID -- `DstChainID (string)`: The destination blockchain ID -- `Number (int)`: A unique number for all packets -- `Status (enum)`: Can be one of `AckPending`, `AckSent`, `AckReceived`, - `NoAck`, or `Timeout` -- `Type (string)`: The types are application-dependent. Cosmos reserves the - "coin" packet type -- `MaxHeight (int)`: If status is not `NoAckWanted` or `AckReceived` by this - height, status becomes `Timeout`. _Optional_ - -IBCPacketTx 이체는 다음으로 구성된다: - -- `FromChainID (string)`: The ID of the blockchain which is providing this - packet; not necessarily the source -- `FromBlockHeight (int)`: The blockchain height in which the following packet - is included (Merkle-ized) in the block-hash of the source chain -- `Packet (IBCPacket)`: A packet of data, whose status may be one of - `AckPending`, `AckSent`, `AckReceived`, `NoAck`, or `Timeout` -- `PacketProof (IAVLProof)`: A IAVLTree Merkle-proof for proving the packet's - hash against the `AppHash` of the source chain at given height - -'허브'를 통해 '존 1'에서 '존 2'로 패킷을 송신하기 위한 순서가 {그림 X}에 도시되어 있다. 먼저, IBCPacketTx 가 패킷이 '존 1'의 앱-상태(app-state)에 포함되어 있음을 '허브'에 증명한다. 그 다음에 또 다른 IBCPacketTx 가 패킷이 '허브'의 앱-상태에 포함되어 있음을 '존 2'에 증명한다. 이 절차 동안, IBCPacket 필드들은 동일하다: SrcChainID 는 언제나 'Zone1(존 1)'이고 DstChainID 는 언제나 'Zone2(존 2)'이다. - -PacketProof 은 반드시 다음과 같은 올바른 머클 증명 경로를 포함해야 한다: - - IBC/<SrcChainID>/<DstChainID>/<Number> - -'존 1'이 '허브'를 통해 '존 2'로 패킷을 전송할 경우, 패킷이 '존 1', '허브' 또는 '존 2'의 어디에서 머클화 되든지 상관 없이 IBCPacket 데이터는 동일하다. 변경 가능한 유일한 필드는 전송 추적을 위한 Status(상태)이다. - -## 감사의 글 (Acknowledgements) - -We thank our friends and peers for assistance in conceptualizing, reviewing, and -providing support for our work with Tendermint and Cosmos. - -- [Zaki Manian](https://github.com/zmanian) of - [SkuChain](http://www.skuchain.com/) provided much help in formatting and - wording, especially under the TMSP section -- [Jehan Tremback](https://github.com/jtremback) of Althea and Dustin Byington - for helping with initial iterations -- [Andrew Miller](https://soc1024.com/) of [Honey - Badger](https://eprint.iacr.org/2016/199) for feedback on consensus -- [Greg Slepak](https://fixingtao.com/) for feedback on consensus and wording -- Also thanks to [Bill Gleim](https://github.com/gleim) and [Seunghwan - Han](http://www.seunghwanhan.com) for various contributions. -- **Your name and organization here for your contribution** - -## 인용 (Citations) - -- [1] Bitcoin: <https://bitcoin.org/bitcoin.pdf> -- [2] ZeroCash: <http://zerocash-project.org/paper> -- [3] Ethereum: <https://github.com/ethereum/wiki/wiki/White-Paper> -- [4] TheDAO: <https://download.slock.it/public/DAO/WhitePaper.pdf> -- [5] Segregated Witness: <https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki> -- [6] BitcoinNG: <https://arxiv.org/pdf/1510.02037v2.pdf> -- [7] Lightning Network: <https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf> -- [8] Tendermint: <https://github.com/tendermint/tendermint/wiki> -- [9] FLP Impossibility: <https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf> -- [10] Slasher: <https://blog.ethereum.org/2014/01/15/slasher-a-punitive-proof-of-stake-algorithm/> -- [11] PBFT: <http://pmg.csail.mit.edu/papers/osdi99.pdf> -- [12] BitShares: <https://bitshares.org/technology/delegated-proof-of-stake-consensus/> -- [13] Stellar: <https://www.stellar.org/papers/stellar-consensus-protocol.pdf> -- [14] Interledger: <https://interledger.org/rfcs/0001-interledger-architecture/> -- [15] Sidechains: <https://blockstream.com/sidechains.pdf> -- [16] Casper: <https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/> -- [17] TMSP: <https://github.com/tendermint/abci> -- [18] Ethereum Sharding: <https://github.com/ethereum/EIPs/issues/53> -- [19] LibSwift: <http://www.ds.ewi.tudelft.nl/fileadmin/pds/papers/PerformanceAnalysisOfLibswift.pdf> -- [20] DLS: <http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf> -- [21] Thin Client Security: <https://en.bitcoin.it/wiki/Thin_Client_Security> -- [22] Ethereum 2.0 Mauve Paper: <https://cdn.hackaday.io/files/10879465447136/Mauve%20Paper%20Vitalik.pdf> - -#### 기타 링크 (Unsorted links) - -- [https://www.docdroid.net/ec7xGzs/314477721-ethereum-platform-review-opportunities-and-challenges-for-private-and-consortium-blockchains.pdf] diff --git a/docs/resources/whitepaper-pt.md b/docs/resources/whitepaper-pt.md deleted file mode 100644 index aff8c86ff962..000000000000 --- a/docs/resources/whitepaper-pt.md +++ /dev/null @@ -1,1482 +0,0 @@ -# Cosmos - -Uma Rede de Distribuição de Ledgers - -Jae Kwon jae@tendermint.com<br/> -Ethan Buchman ethan@tendermint.com - -Para discussões, [entre no nosso Matrix](https://riot.im/app/#/room/#cosmos:matrix.org)! - -_NOTA: Se você pode ler isso no GitHub, então ainda estamos desenvolvendo este documento ativamente. Por favor, cheque regularmente as atualizações!_ - -\[[toc]] - -O sucesso combinado do ecossistema de código aberto, compartilhamento -de arquivos descentralizado e criptomoedas públicas tem inspirado um conhecimento sobre -protocolos descentralizados na Internet que podem ser utilizados para melhorar radicalmente -a infraestrutura. Vimos aplicações de blockchain especializadas como Bitcoin -[\[1\]][1] (uma criptomoeda), Zerocash [\[2\]][2] (uma criptomoeda para privacidade -), and generalized smart contract platforms such as Ethereum [\[3\]][3], -com inúmeras aplicações distribuídas para a Etherium Virtual Machine (EVM), como Augur (uma previsão -de mercado) e TheDAO [\[4\]][4] (um clube de investimento). - -Contudo, até à data, estas blockchains sofreram uma série de inconvenientes, -incluindo sua ineficiência energética, desempenho fraco ou limitado e -mecanismos de governança imaturos. Propostas de escala -de processamento de transações da Bitcoin, como Testemunhas Separadas [\[5\]][5] e -BitcoinNG [\[6\]][6], soluções de escalonamento vertical que permanecem -limitadas pela capacidade de uma única máquina física, a fim de -proporcionar uma auditabilidade completa. A Rede Lightning [\[7\]][7] pode ajudar -o Bitcoin no quesito volume de transações, deixando algumas transações completamente -fora da carteira, e é bem adequado para micropagamentos e preservando a privacisadade por pagamentos -Rails, mas pode não ser adequado para necessidades de escala mais abrangente. - -Uma solução ideal é a de permitir blockchains paralelos múltiplos para -interoperação, mantendo suas propriedades de segurança. Isto provou -ser difícil, se não impossível, com prova de trabalho. A mineração combinada, por exemplo, -permite que o trabalho feito para proteger uma blockchain mãe seja reutilizado em uma blockchain nova, -mas as transações ainda devem ser validadas, em ordem, por cada nó, e uma -blockchain Merge-mined é vulnerável a ataques se a maioria do poder de -hashing sobre a mãe não é ativamente merge-mined da nova. Uma revisão acadêmica -do [arquiteturas de redes alternativas blockchain -](http://vukolic.com/iNetSec_2015.pdf) é fornecida para -contextualizar, e fornecemos resumos de outras propostas e suas desvantagens em -[Trabalho relatado](#trabalho-relatado). - -Nesse relato nós apresentamos a Cosmos, uma novela da arquitetura de rede blockchain que aborda todos -esses problemas. Cosmos é uma rede de muitos blockchains independentes, chamados -Zonas. As zonas são alimentadas pelo Tendermint Coreork [\[8\]][8], que fornece uma -alta performace, consistência, segurança -[PBFT-como](https://blog.cosmos.network/tendermint-vs-pbft-12e9f294c9ab?gi=20a63f2a00ee) um mecanismo de consenso -rigoroso, onde [fork-responsável](#fork-responsável) tem-se garantias de deter -comportamentos maliciosos. O algoritmo de consenso BFT do Tendermint Core é -bem adaptado para integrar blockchains públicas de prova de estaca. - -A primeira zona na Cosmos é chamada de Cosmos Hub. A Cosmos Hub é uma criptomoeda -multi-asset de prova de estaca com um simples mecanismo de governança -o qual permite a rede se adaptar e atualizar. Além disso, a Cosmos Hub pode ser -extendida por conexão com outras zonas. - -O hub e as zonas da rede Cosmos comunicam-se uma com a outra através de um -protocolo de comunicação Inter-blockchain (IBC), um tipo de UDP ou TCP virtual para -blockchains. Os tokens podem ser transferidos de uma zona para outra com segurança e -rapidez sem necessidade de liquidez cambial entre as zonas. Em vez disso, todas -as transferências de tokens inter-zonas passam pelo Hub Cosmos, que mantêm -a quantidade total de tokens detidas por cada zona. O hub isola cada zona da -falha das outras zonas. Porque qualquer um pode conectar uma nova zona no Hub Cosmos, -o que permite futuras compatibilidades com novas blockchains inovadoras. - -## Tendermint - -Nesta seção, descrevemos o protocolo de consenso da Tendermint e a interface -usada para construir aplicações através dele. Para mais detalhes, consulte o [apêndice](#apêndice). - -### Validadores - -No algorítimo de tolerância e falhas clássicas Bizantinas (BFT), cada node tem o mesmo -peso. Na Tendermint, nodes tem uma quantidade positiva de _poder de voto_, e -esses nodes que tem poder de voto positivo são chamados de _validadores_. Validadores -participam de um protocolo de consenso por transmissão de assinaturas criptográficas, -ou _votos_, para concordar com o próximo bloco. - -Os poderes de voto dos validadores são determinados na gênese, ou são alterados -de acordo com a blockchain, dependendo da aplicação. Por exemplo, -em uma aplicação de prova de participação, como o Hub da Cosmos, o poder de voto pode ser -determinado pela quantidade de tokens usados como garantia. - -_NOTA: Frações como ⅔ e ⅓ referem-se a frações do total de votos, -nunca o número total de validadores, a menos que todos os validadores tenham -peso._ -_NOTE: +⅔ significa "mais do que ⅔", enquanto ⅓+ significa "⅓ ou mais"._ - -### Consenso - -Tendermint é um protocolo de consenso BFT parcialmente sincronizado e derivado do -algoritmo de consenso DLS [\[20\]][20]. Tendermint é notável por sua simplicidade, -desempenho, e [fork-responsável](#fork-responsável). O protocolo -requer um grupo determinado de validadores, onde cada validador é identificado por -sua chave pública. Validadores chegarão a um consenso em um bloco por vez, -onde um bloco é uma lista de transações. A votação para o consenso sobre um bloco -acontece por rodada. Cada rodada tem uma líder-de-rodada, ou proponente, que propõe um bloco. Os -validadores, em seguida, votam, por etapas, sobre a aceitação do bloco proposto -ou passam para a próxima rodada. O proponente de uma rodada é escolhido -de acordo com uma lista ordenada de validadores, proporcionalmente à seu -poder de voto. - -Os detalhes completos do protocolo estão descritos -[aqui](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - -A segurança da Tendermint é baseada na tolerância e falhas clássicas Bizantinas ótimas -através de super-maioria (+⅔) e um mecanismo de bloqueio. Juntas, elas garantem -isso: - -- ⅓+ o poder de voto deve ser bizantino devido a violações de segurança, onde mais -   que dois valores são comprometidos. -- se algum conjunto de validadores tiver sucesso em violar a segurança, ou mesmo tentarem - para isso, eles podem ser identificados pelo protocolo. Isso inclui tanto o voto - para blocos conflitantes quanto a transmissão de votos injustificados. - -Apesar de suas fortes garantias, a Tendermint oferece um desempenho excepcional. Dentro -de Benchmarks de 64 nós distribuídos em 7 datacenters em 5 continentes, em -nuvens de commodities, o consenso da Tendermint pode processar milhares de -transações por segundo, com tempo de resposta entre um a dois -segundos. Notavelmente, o desempenho muito além de mil transações por segundo -é mantido mesmo em condições adversas, com validadores falhando ou -combinando votos maliciosamente. Veja a figura abaixo para mais detalhes. - -![Figura do desempenho da Tendermint](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/tendermint_throughput_blocksize.png) - -### Clientes Light - -O principal benefício do algoritmo de consenso da Tendermint é um cliente leve e simplificado -de segurança, tornando-o um candidato ideal para o uso de dispositivos móveis e casos de uso na -internet. Enquanto um cliente leve do Bitcoin deve sincronizar blockchains e encontrar -o que tem mais prova de trabalho, os clientes light da Tendermint precisa apenas -das alterações feitas pelo conjunto dos validadores, em seguida, verifica-se o +⅔ PreCommits -no último bloco para determinar o estado atual. - -Provas claras e sucintas do cliente também permite [comunicação-inter- -blockchain](#comunicação-inter-blockchain-ibc). - -### Previnindo ataques - -A Tendermint dispõe de medidas de proteção para evitar -ataques, como [gastos duplos em longa-distância-sem-estaca double -spends](#previnindo-ataques-de-longa-distância) e -[censura](#superando-forks-e-censurando-ataques). Esses são discutidos -completamente no [apêndice](#apêndice). - -### TMSP - -O algoritmo de consenso Tendermint é implementado através de um programa chamado Tendermint -Core. O Tendermint Core é um "mecanismo de consenso" independente de aplicações que -transformam qualquer aplicação blackbox em uma réplica distribuída na -Blockchain. Tendermint Core conecta-se ao blockchain -através de aplicações do Tendermint Socket Protocol (TMSP) [\[17\]][17]. Assim, o TMSP -permite que as aplicações da blockchain sejam programadas em qualquer idioma, não apenas -a linguagem de programação que o mecanismo de consenso é escrito, além disso, -o TMSP torna possível a troca fácil da camada de consenso de qualquer -tipo de blockchain. - -Nós fizemos uma analogia com a bem conhecida criptogradia do Bitcoin. Bitcoin é uma -blockchain de criptomoedas onde cada nó mantém uma Unspent totalmente auditada -e banco de dados de saída de transação (UTXO). Se alguém quisesse criar um Bitcoin-like -TMS, a Tendermint Core seria responsável por - -- Compartilhar blocos e transações entre os nós -- Estabelecer uma ordem de transações canônica/imutável (a blockchain) - -Entretanto, o aplicativo TMSP seria responsável por - -- Manter o banco de dados UTXO -- Validar a criptografia das assinaturas das transações -- Previnir transações vindas de gastos de fundos não exisentes -- Permitir aos clientes a consulta do banco de dados UTXO - -Tendermint é capaz de decompor o design da blockchain, oferecendo um simples -API entre o processo da aplicação e o processo do consenso. - -## Visão Geral da Cosmos - -Cosmos é uma rede de blockchains paralelos e independentes que são alimentadas pelo -clássico algorítimo de consenso BFT como a Tendermint -[1](https://github.com/tendermint/tendermint). - -A primeira blockchain dessa rede será a Cosmos Hub. A Cosmos Hub -conecta as outras blockchains (ou _zonas_) através do protocolo de comunicação-inter- -blockchain. A Cosmos Hub rastreia vários tipos de tokens e mantém -registo do número total de tokens em cada zona ligada. Os tokens podem ser -transferidos de uma zona para outra de forma segura e rápida, sem necessidade de -uma troca líquida entre zonas, porque todas as transferências de moedas ocorre -através da Cosmos Hub. - -Essa arquitetura resolve muitos dos problemas enfrentados atualmente pelas blockchains, -tais como interoperabilidade de aplicativos, escalabilidade e capacidade de atualização contínua. -Por exemplo, as zonas baseadas do Bitcoin, Go-Ethereum, CryptoNote, ZCash, ou qualquer -sistema blockchain pode ser ligado ao Cosmos Hub. Essas zonas permite a Cosmos -o escalonamento infinito para atender a demanda global de transações. As Zonas também são um grande -apoio para a exchange distribuída, que também serão apoiadas. - -Cosmos não é apenas uma única ledger distribuídos, o Cosmos Hub não é um -jardim cercado ou o centro do universo. Estamos elaborando um protocolo para -uma rede aberta de legers distribuídos que pode servir como um novo -futuros para sistemas financeiros, baseados em princípios de criptografia, economia -teoria de consenso, transparência e responsabilidade. - -### Tendermint-BFT - -O Cosmos Hub é a primeira blockchain pública na rede Cosmos, alimentada pelo -algoritimo de consenso BFT Tendermint. A Tendermint é um projeto de fonte aberta que -nasceu em 2014 para abordar a velocidade, a escalabilidade e as questões -do algoritimo de consenso da prova-de-trabalho do Bitcoin. Usando e melhorando -algoritmos BFT comprovados e desenvolvidos no MIT em 1988 [\[20\]][20], o time Tendermint foi o primeiro a -que demonstrou conceitualmente uma prova de estaca das criptomoedas que aborda o -problema de "sem-estaca" sofrido pelas criptomoedas da primeira geração -tais como NXT e BitShares. - -Hoje, praticamente todas carteiras móveis de Bitcoin usam servidores confiáveis, que fornece -a elas transações com verificação. Isso porque a prova-de-trabalho exige -muitas confirmações antes que uma transação possa ser considerada -irreversivel e completa. Os ataques de gasto-duplo já foram demonstrados em -serviços como a CoinBase. - -Ao contrário de outros sistemas de consenso blockchain, a Tendermint oferece -comprovação segura de pagamento para o cliente móvel. Uma vez que a Mint é -projetada para nunca passar por um fork, carteiras móveis podem receber confirmações de transações -instantâneas, o que torna os pagamentos confiáveis e práticos através de -smartphones. Isto tem implicações significativas para as aplicações da Internet. - -Validadores na Cosmos tem uma função similar aos mineiros do Bitcoin, mas usam -assinaturas criptografadas para votar. Validadores são máquinas seguras e dedicadas -que são responsáveis por validar os blocos. Os não validadores podem delegar através de seus tokens estacados -(chamados "atoms") a qualquer validador para ganhar uma parcela das taxas da blockchain -e recompensas de atoms, mas eles correm o risco de serem punidos (cortados) se o -o validador de delegados for invadido ou violar o protocolo. A segurança comprovada -garantida pelo consenso BFT da Tendermint, e o depósito de garantia das -partes interessadas - validadores e delegados - fornecem dados prováveis, -segurança para os nós e clientes light. - -### Governança - -Ledgers de distribuição pública devem ser constituídos de um sistema de governança. -O Bitcoin confia na Fundação Bitcoin e na mineração para -coordenar upgrades, mas este é um processo lento. Ethereum foi dividido em ETH e -ETC depois de hard-fork para se recuperar do hack TheDAO, em grande parte porque não havia -contrato sócial prévio, nem um mecanismo para tomar tais decisões. - -Os validadores e os delegados do Cosmos Hub podem votar propostas que -alteraram automaticamente os parâmetros predefinidos do sistema (tal como o gás limite do -bloco), coordenar upgrades, bem como votar em emendas para a -constituição que governa as políticas do Cosmos Hub. A Constituição -permite a coesão entre as partes interessadas em questões como o roubo -e bugs (como o incidente TheDAO), permitindo uma resolução mais rápida e mais limpa. - -Cada zona pode ter sua própria constituição e mecanismo de governança. -Por exemplo, o Cosmos Hub pode ter uma constituição que reforça a imutabilidade -no Hub (sem roll-backs, a não ser por bugs em implementações dos nós do Cosmos Hub), -enquanto cada zona pode ter sua própria política sobre os roll-backs. - -Ao disponibilizar a interoperabilidade em diferentes políticas das zonas, a rede Cosmos -dá aos usuários total liberdade e potenciais permissões para -experimentos. - -## O Hub e as Zonas - -Aqui nós descrevemos o modelo do roteiro de descentralização e ecalabilidade. Cosmos é uma -rede de muitas blockchains alimentadas pela Tendermint. Enquanto existirem propostas visando -criar um"blockchain solitário" com ordens de transações cheias, a Cosmos -permite que muitas blockchains rodem junto de outra enquanto mantêm a -interoperabilidade. - -Basicamente, o Cosmos Hub gerencia várias blockchains independentes chamadas "zonas" -(as vezes chamadas de "shards", em referência a técnica de escalonamento de -bando de dados conhecida como "sharding"). Uma constante transmissão de blocos recentes das -zonas atuando no Hub permite ao Hub manter o estado de cada zona atualizado. -Sendo assim, cada zona mantêm ativa o estado do Hub (mas as zonas não se mantêm ativas -com qualquer outro exceto o Hub). Pacotes de informação são -então comunicados de uma zona para outra atráves de Merkle-proofs como evidências, -essas informações são enviadas e recebidas. Esse mecanismo é chamado de -comunicação inter-blockchain, ou IBC para encurtar. - -![Figura de reconhecimento -do hub e das zonas](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/hub_and_zones.png) - -Qualquer uma das zonas podem ser hubs para formar gráficos acíclicos, mas -mas para deixar claro, nós vamos apenas descrever uma simples configuração para -um único hub, e várias zonas que não são hubs. - -### O Hub - -O Cosmos Hub é uma blockchain que hospeda um ledger de distribuíção de multi-asset, -onde os tokens podem ser mantidos por usuários individuais ou pelas próprias zonas. Esses -tokens podem ser movidos de uma zona para outra em um pacote IBC especial chamado -"coin packet". O hub é responsavel por preservar a manutenção global de -toda a quantia de cada token nas zonas. As transações de moedas no pacote IBC -precisam ser feitas pelo remetente, hub, e blockchain recebedor. - -Desde a atuação do Cosmos Hub como ledger principal para todos o -sistema, a segurança do Hub é de suma importância. Enquanto cada -zona pode ser uma blockchain Tendermint que é segurada por 4((ou talvez -menos caso o consenso BFT não seja necessário), o Hub precisa ser segurado por uma descentralização -globalizada feita pelos validadores que podem evitar os mais severos tipos de -ataques, como uma partição de rede continental ou um estado-nação fazendo -ataques. - -### As Zonas - -Uma zona Cosmos é uma blockchain independente das trocas de mensagens IBC com o -Hub. Na perspectiva do Hub, uma zona é uma conta multi-asset dynamic-membership -multi-signature que pode enviar e receber tokens usando pacotes IBC. Como -uma conta de criptomoeda, uma zona não pode transferir mais tokens do que ela possui, mas -pode receber tokens de outras que os tem. Uma zona pode ser usada como uma -"fonte" de um ou mais tipos de tokens, garantindo o poder de aumentar o estoque desse -token. - -Os atoms do Cosmos Hub podem ser estacados por validadores de uma zona conectada ao -Hub. Enquanto os ataques de gasto-duplo nesses zonas podem resultar em um core dos -atoms com o fork-responsável da Tendermint, uma zona onde +⅔ do poder de voto -são Bizantinos podem deixar o estado inválido. O Cosmos Hub não verifica ou -executa transações ocorridas em outras zonas, então essa é uma responsabilidade dos -usuários para enviar os tokes ara zonas que eles confiem. Futuramente, o sistema de -governança do Cosmos Hub irá implementar propostas para o Hub e para as falhas -das zonas. Por exemplo, um token de saída transferido para algumas (ou todas) zonas podem ser -segurados em caso de uma emergência de quebra de circuito das zonas(uma parada temporária -nas transferências dos tokens) quando um ataque é detectado. - -## Comunicação Inter-blockchain (IBC) - -Agora nós olhamos para como o Hub e as zonas vão se comunicar. Por exemplo, se -aqui são três blockchains, "Zona1", "Zona2", and "Hub", e nós queremos que a -"Zona1" produza um pacote destinado para a "Zona2" indo através do "Hub". Para mover um -pacote de uma blockchain para outra, uma prova é feita na -cadeia recebedora. A prova atesta esse envio publicado na cadeia de destino por uma alegação -de pacote. Para a cadeia recebedora checar essa prova, isso é possível -por um block principal de envio. Esse mecanismo é similar ao usado por -cadeias paralelas, que requerem duas cadeias interagindo uma com a outra via -transmissões bidirecionais por dados de prova-de-existência (transações). - -O protocolo IBC pode naturalmente ser definido usando dois tipos de transações: uma -transação `IBCBlockCommitTx`, a qual permite uma blockchain provar para qualquer -espectador o mais recente hash-de-bloco, e uma transação `IBCPacketTx`, a qual -permite uma blockchain provar para qualquer espectador que o pacote recebido foi realmente -publicado pelo remetente, via Merkle-proof para um hash-de-bloco -recente. - -Ao misturar o mecanismo ICB em duas transações separadas, nós permitimos -que o mecanismo de mercado de taxa nativa da blockchain recebedora determine quais pacotes -irão se comprometer (isto é, ser reconhecido), permitindo simultaneamente que uma -blockchain envie de quantos pacotes de saída forem permitidos. - -![Figura da Zona1, Zona2, e Hub IBC sem -reconhecimento](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_without_ack.png) - -No exemplo acima, para atualizar o hash de blocos da -"Zona1" no "Hub" (ou do "Hub" para a "Zona2"), uma transação `IBCBlockCommitTx` -precisa ser feita no "Hub" com o hash de bloco da "Zona1" (ou na -"Zona2" com o hash de bloco do "Hub"). - -_Veja [IBCBlockCommitTx](#ibcblockcommittx) e [IBCPacketTx](#ibcpacketcommit) -para mais informações sobre os 2 tipos de transação IBC._ - -## Casos de Uso - -### Exchange Distribuídas - -Da mesma forma que Bitcoin é mais seguro por ter uma distribuíção, -e replicação em massa, podemos tornar as exchanges menos vulneráveis a -Hacks internos executando-a no blockchain. Chamamos isso de exchange -distribuída. - -O que a comunidade de criptomoedas chama hoje de intercâmbio descentralizado -baseado em algo chamado transações "atomic cross-chain" (AXC). Com uma transação -AXC, dois usuários em duas diferentes cadeias podem fazer duas transações -de transferências que serão feitas juntas nas duas ledgers, ou nenhuma (isto é, -Atomicamente). Por exemplo, dois usuários podem trocar bitcoins por ether (ou qualquer dois -Tokens em dois ledgers diferentes) usando transações AXC, mesmo que o Bitcoin -e o Ethereum não estão conectados entre si. O benefício de executar um -troca em transações AXC é que nenhum dos usuários precisam confiar um no outro ou -no serviço de correspondência comercial. A desvantagem é que ambas as partes precisam estar -on-line para o negócio ocorrer. - -Outro tipo de intercâmbio descentralizado é um sistema de -exchange que funciona em seu próprio blockchain. Os usuários deste tipo de exchange podem -enviar uma ordem de limite e desligar o computador, e o negócio pode ser executado -sem que o usuário esteja online. O blockchain combina e completa o negócio -em nome do negociante. - -Uma exchange centralizada pode criar um vasto livro de ordens de ordens e -atrair mais comerciantes. A liquidez gera mais liquidez no mundo cambial, -e assim há um forte efeito na rede (ou pelo menos efeito de vencedor-leva-mais) -no negócio de câmbio. A atual líder para troca de criptomoedas -hoje é a Poloniex com um volume de 24 milhões de dólares por dia, e em segundo lugar a -Bitfinex com um volume de US$5 milhões por dia. Dados esses fortes efeitos na rede, -é improvável que as exchanges descentralizadas baseadas no AXC ganhem volume -centrais. Para uma exchange descentralizada competir com um -exchange centralizada, seria necessário dar suporte aos livros de -ordens. Somente uma exchange distribuída em uma blockchain pode fornecer isso. - -Tendermint fornece benefícios adicionais para realizar uma transação mais rápida. Com a -finalidade de dar prioridade a rapidez sem sacrificar a consistência, as zonas no Cosmos podem -finalizar transações rápidas - tanto para transações de ordem de -transferências de tokens quanto para outras zonas IBC. - -Dado o estado das exchanges de criptomoedas hoje em dia, uma grande -exchange distribuída da Cosmos (aka o Cosmos DEX). A transação e -a capacidade de processamento, bem como a latência de processos, podem ser -centrais. Os comerciantes podem enviar ordens de limite que podem ser executadas -sem que ambas as partes tenham que estar online. E com Tendermint, o Cosmos Hub, -e o IBC, os comerciantes podem mover fundos dentro e fora da exchange e para outras -zonas com rapidez. - -### Pegging para Outras Criptomoedas - -Uma zona privilegiada pode agir como token simbolico de uma -criptomoeda. A peg é semelhante à relação entre uma -zona e o Cosmos Hub; Ambos devem manter-se atualizados com os -outros, afim de verificar provas de que os tokens passaram de um para o outro. A -Peg-zone na rede Cosmos mantém-se com o Hub, bem como o -outra cryptomoeda. A indireção através da peg-zone permite a lógica de -que o Hub permaceça simples e imutável para outras estratégias de consenso blockchain -como a mineração de prova-de-trabalho do Bitcoin. - -Por exemplo, uma zona Cosmos com um conjunto validador específico, possivelmente o mesmo que -o Hub, poderia atuar como um ether-peg, onde a aplicação TMSP sobre -a zona ("peg-zone") tem mecanismos para trocar mensagens IBC com um -Peg-contract na blockchain (a "origem"). Este contrato -permite que os titulares de ether enviem ether para a zona de peg, enviando-o para -Peg-contract na Ethereum. Uma vez que o ether é recebido pelo peg-contract, o ether -não pode ser retirado a menos que um pacote IBC apropriado seja recebido pelo -Peg-contract da peg-zone. Quando uma zona recebe um pacote IBC provando -que o ether foi recebido no peg-contract para uma determinada conta Ethereum, -a conta correspondente é criada na peg-zone com esse saldo. O ether na -peg-zone ("pegged-ether") pode então ser transferido para o Hub, -e mais tarde ser destruído com uma transação que envia para um determinado -endereço de retirada no Ethereum. Um pacote IBC provando que a transação -na Peg-Zone podem ser lançados no peg-contract Ethereum para permitir que o -Ether seja retirado. - -Naturalmente, o risco do contrato do pegging e um conjunto de validadores desonestos. -bizantino. -O poder de voto bizantino poderia causar um fork, retirando o ether do -peg-contract mantendo o pegged-ether na peg-zone. Na pior das hipóteses, -\+⅔ do poder de voto bizantino pode roubar o ether daqueles que o enviaram para o -peg-contract, desviando-se da pegging e da peg-zone de origem. - -É possível abordar essas questões projetando o peg para ser totalmente -responsável. Por exemplo, todos os pacotes IBC, a partir do hub de -origem, poderão exigir um reconhecimento pela zona de fixação de tal forma que -as transições de estados da peg-zone podem ser desafiadas de forma eficiente e verificadas pelo -hub ou pelo peg-contract de origem. O Hub e a origem devem -permitir que os validadores da zona de fixação apresentem garantias e as transferências -contratuais devem ser atrasadas (e um prazo de vinculação de colateral suficientemente -longo) para permitir que quaisquer desafios sejam feitos por auditores independentes. Nós saímos -da concepção, da especificação e implementação deste sistema aberto como uma -futura proposta de melhoria da Cosmos, a ser aprovada pela governança do sistema do Cosmos -Hub. - -Embora a atmosfera sociopolítica ainda não esteja bastante desenvolvida, podemos -aumentar o mecanismo para permitir que as zonas se liguem as moedas FIAT de um -estado-nação, formando um validador responsável estabelecido a partir de uma combinação da -moeda da nação, mais particularmente, pelos seus bancos. Claro, -precauções adicionais devem ser tomadas para aceitar apenas moedas apoiadas por -sistemas que possam reforçar a capacidade de auditoria das atividades dos bancos -e de notário grupos de grandes instituições de confiança. - -Um resultado dessa integração poderia ser, por exemplo, permitir que -uma conta em um banco na zona possa mover dólares de sua conta bancária -para outras contas na zona, ou para o hub, ou inteiramente para outra zona. -Nesse sentido, o Cosmos Hub pode atuar como um canal sem -moedas e criptomoedas, removendo as barreiras que limitariam -sua interoperabilidade com o mundo dos intercâmbios. - -### Ethereum Scaling - -Resolver o problema de escalonamento é um problema aberto para a Ethereum. Atualmente, -os nós Ethereum processam cada transação única e também armazenam todos os estados. -[link](https://docs.google.com/presentation/d/1CjD0W4l4-CwHKUvfF5Vlps76fKLEC6pIwu1a_kC_YRQ/mobilepresent?slide=id.gd284b9333_0_28). - -Desde que a Tendermint pode realizar os blocos muito mais rápido do que a prova-de-trabalho da Ethereum, -as zonas EVM alimentadas e operando pelo consenso da Tendermint -fornecem maior desempenho para blocos da blockchain Ethereum. Além disso, embora o -Cosmos Hub e o mecanismo de pacotes IBC não permitam a execução da lógica de contratos -arbitrários, podem ser usados para coordenar os movimentos Ethereum e a execução de -contratos simbólicos em diferentes zonas, fornecendo uma base para -o token ethereum através de sharding. - -### Integração de Multi-Aplicação - -As zonas Cosmos executam lógica de aplicação arbitrária, que é definida no início da -vida da zona e podem potencialmente ser atualizados ao longo do tempo pela governança. Essa flexibilidade -permite que as zonas Cosmos ajam como pegs para outras criptomoedas como Ethereum ou -Bitcoin, e também permite derivados desses blockchains, que utilizam a -mesma base de código, mas com um conjunto de validador diferente e distribuição inicial. Isto -permite que muitos tipos de criptomoedas existentes, como as Ethereum, -Zerocash, Bitcoin, CryptoNote e assim por diante, possam ser usados com o Tendermint Core, -que é um motor de consenso de maior desempenho, em uma rede comum, abrindo -oportunidade de interoperabilidade entre as plataformas. Além disso, como -multi-asset blockchain, uma única transação pode conter vários -onde cada entrada pode ser qualquer tipo de token, permitindo a Cosmos -ser uma plataforma para a exchange descentralizada, mesmo que as ordens sejam -para outras plataformas. Alternativamente, uma zona pode servir como um -fault-tolerant (com livros de ordens), o que pode ser uma melhoria -nas exchanges centralizadas de criptomoeda que tendem a ser invadidas com -o tempo. - -As zonas também podem servir como versões bloqueadas de empresas e -sistemas, onde partes de um serviço particular da organização ou grupo de organizações -que são tradicionalmente executadas como um aplicativo TMSP -em uma certa zona, o que lhe permite receber a segurança e a interoperabilidade da -rede pública Cosmos sem sacrificar o controle sobre o serviço subjacente. -Assim, a Cosmos pode oferecer o melhor da tecnologia blockchain para ambos os mundos e -para as organizações, que se recusam a deixar completamente o controle -para um distribuidor terceirizado. - -### Redução de partição de rede - -Alguns afirmam que um grande problema da coerência-favorecendo algoritmos de consenso -como o Tendermint é que qualquer partição de rede que faz com que não haja uma única -partição com +⅔ de poder de votação (por exemplo, ⅓+ ficando offline) irá parar o consenso -completamente. A arquitetura Cosmos pode ajudar a mitigar esse problema usando umas -zonas regionais autônomas, onde o poder de voto para cada zona é -distribuído com base em uma região geográfica comum. Por exemplo, um -parâmetro pode ser para cidades individuais, ou regiões, para operar suas próprias zonas -de partilha com um centro em comum (por exemplo, o Cosmos Hub), permitindo que a -o hub possa parar devido a uma paralisação de rede temporária. -Observe que isso permite uma geologia real, política e rede-topológica, -que são recursos a serem considerados no projeto de sistemas robustos federados de fault-tolerant. - -### Sistema de Resolução de Nomes Federados - -NameCoin foi uma das primeiras blockchains a tentar resolver o -problema de resolução de nomes através de uma adaptação da blockchain do Bitcoin. Infelizmente -têm ocorrido várias questões com esta abordagem. - -Com a Namecoin, podemos verificar que, por exemplo, o nome <em>@satoshi</em> foi registrado como -particular, em algum momento do passado, mas não saberíamos se -a chave pública tinha sido atualizada recentemente, a menos que baixassemos todos os blocos -desde a última atualização desse nome. Isto é devido as limitações do modelo de -Merkle-ization de UTXO do Bitcoin, onde somente as transações (não -mutáveis) são Merkle-ized no hash do bloco. Isso nos permite -provar a existência, mas não a não-existência de atualizações posteriores a um nome. Assim, nós -não podemos saber com certeza o valor mais recente de um nome sem confiar em um -nó, ou recorrer a gastos significativos na largura de banda, baixando o -Blockchain. - -Mesmo se uma árvore de pesquisa Merkle-ized for implementada na NameCoin, sua dependência -sobre a prova-de-trabalho torna a verificação do cliente light problemática. Os clientes light devem -baixar uma cópia completa dos cabeçalhos para todos os blocos em toda a blockchain -(ou pelo menos todos os cabeçalhos desde a última atualização de um nome). Isso significa que -os requisitos de largura de banda crescem linearmente com a o passar do tempo [\[21\]][21]. -Além disso, as mudanças de nome em um bloco de prova-de-trabalho requerem -a confirmação do trabalho, o que pode levar até uma hora -no Bitcoin. - -Com Tendermint, tudo o que precisamos é o hash de bloco mais recente assinado por um quorum de -validadores (por poder de voto), e uma prova Merkle para o valor atual associado -com o nome. Isto torna possível ter uma solução sucinta, rápida e segura -para a verificação de valores de nome no cliente light. - -Na Cosmos, podemos aplicar este conceito e estendê-lo ainda mais. Cada -zona de registro de nomes na Cosmos pode ter um domínio de nível superior (TLD) -associado, como o ".com" ou ".org", e cada zona de registro de nome pode ter -suas próprias regras de governança e registro. - -## Emissão e Incentivos - -### O Token Atom - -Enquanto o Cosmos Hub é um ledger de distribuíção multi-asset, há um token nativo -especial chamado _atom_. Os atoms são o únicos símbolos do Cosmos -Hub. Os atoms são uma licença para o titular votar, validar ou delegar -validadores. Como o ether da Ethereum, os atoms também podem ser usados para -reduzir o spam. Atoms inflacionários adicionais e as taxas do bloco de transação -são recompensadas pelos validadores e delegados que -o validarão. - -A transação `BurnAtomTx` pode ser usada para cobrir proporcionalmente a quantidade -de tokens reservados para a pool. - -#### Levantamento de Fundos - -A distribuição inicial dos tokens atom e validadores na Genesis vão para os -doadores do Levantamento de Fundos da Cosmos (75%), doadores pesados (5%), Fundação da Rede -Cosmos (10%), e a ALL IN BITS, Inc (10%). A partir da Genesis em diante, 1/3 da -quantidade total de atoms será recompensada aos validadores e delegados durante -todo o ano. - -Veja o [Plano Cosmos](https://github.com/cosmos/cosmos/blob/master/PLAN.md) -para detalhes adicionais. - -#### Investindo - -Para evitar que o levantamento de fundos atraia especuladores de curto prazo apenas interessados -em esquemas de pump and dump, os atoms da Genesis não serão transferíveis até -eles tenham investido. Cada conta irá adquirir atoms durante um período de 2 anos com -taxa constante a cada hora, determinada pelo número total de atoms da Genesis/(2* -365 * 24) horas. Os atoms ganhos pela recompensa do bloco são pré-investidos, -e podem ser transferidos imediatamente, de modo que os validadores e os delegados ligados possam ganhar -mais da metade de seus atoms da Genesis após o primeiro ano. - -### Limitações do Número de Validadores - -Diferentemente do Bitcoin ou de outros blockchains de prova-de-trabalho, o blockchain Tendermint será -mais lento com mais validadores devido ao aumento da complexidade da comunicação. -Felizmente, podemos oferecer suporte a validadores suficientes para a -distribuição na Blockchain com tempos de confirmação de transação muito mais rápidos e, através de -largura de banda, armazenamento e aumento da capacidade de computação paralela, seremos capazes de -ter mais validadores no futuro. - -No dia da Genesis, o número máximo de validadores será definido como 100, -o número aumentará a uma taxa de 13% durante 10 anos até atingir a marca de 300 -Validadores. - - Ano 0: 100 - Ano 1: 113 - Ano 2: 127 - Ano 3: 144 - Ano 4: 163 - Ano 5: 184 - Ano 6: 208 - Ano 7: 235 - Ano 8: 265 - Ano 9: 300 - Ano 10: 300 - ... - -### Tornando-se um Validador depois do dia da Genesis - -Os titulares de atoms que ainda não são capazes de se tornarem validadores assinados e -submeter uma transação `BondTx`. A quantidade de atoms fornecida como garantia -deve ser diferente de zero. Qualquer pessoa pode se tornar um validador a qualquer momento, exceto quando o -tamanho do conjunto de validadores atual é maior que o número máximo de -validadores permitidos. Nesse caso, a transação só é válida se o montante -de atoms é maior do que a quantidade de atoms efetivos mantidos pelo menor -validador, onde atoms eficazes incluem atoms delegados. Quando um novo validador -substitui um validador existente de tal forma, o validador existente torna-se -inativo e todos os atoms e atoms delegados entram no estado de unbonding. - -### Penalidades para Validadores - -Deve haver alguma penalidade imposta aos validadores por qualquer desvio intencional -ou não intencional do protocolo sancionado. Algumas evidências são imediatamente admissíveis, -como um double-sign na mesma altura e volta, ou uma violação de "prevote-the-lock" -(uma regra do protocolo de consenso Tendermint). Tais evidências resultarão em que o -validador perca sua boa reputação e seus átomos ligados, bem como sua proporção de tokens -na pool reserva - coletivamente chamados de "stake" - serão cortados. - -Às vezes, os validadores não estarão disponíveis, devido a interrupções na rede regional, -falha de energia ou outros motivos. Se, em qualquer ponto nos blocos `ValidatorTimeoutWindow` -anteriores, o voto de validação de um validador não estiver incluído na cadeia de -blocos mais do que `ValidatorTimeoutMaxAbsent` vezes, esse validador ficará inativo e -perderá `ValidatorTimeoutPenalty` (PADRÃO DE 1%) de sua participação. - -Alguns comportamentos "maliciosos" não produzem provas obviamente discerníveis sobre -a blockchain. Nesses casos, os validadores podem coordenar fora da banda para forçar -o tempo limite desses validadores maliciosos, se houver um consenso majoritário. - -Em situações em que o Cosmos Hub parar devido a uma coalizão de ⅓+ de poder de voto -offline, ou em situações onde uma coalizão de ⅓+ de poder de voto censurar evidências de -comportamento malicioso entrando na blockchain, o hub deve recuperar com um hard-fork -de proposta reorganizacional. (Link to "Forks and Censorship Attacks"). - -### Taxas de Transação - -Os validadores do Cosmos Hub podem aceitar qualquer tipo de token ou combinação -de tipos como taxas para processar uma transação. Cada validador pode fixar subjetivamente a -taxa de câmbio que quiser e escolher as transações que desejar, desde que o `BlockGasLimit` -não seja excedido. As taxas cobradas, menos quaisquer impostos especificados abaixo, -são redistribuídas aos stakeholders ligados em proporção aos seus átomos ligados, cada `ValidatorPayoutPeriod` (PADRÃO DE 1 hora). - -Das taxas de transação cobradas, `ReserveTax` (PADRÃO DE 2%) irá para a pool reserva -para aumentar a pool reserva e aumentar a segurança e o valor da rede Cosmos. Além disso, um -`CommonsTax` (PADRÃO DE 3%) irá para o financiamento de bens comuns. Estes fundos vão para o -`CustodianAddress` para ser distribuído de acordo com as decisões tomadas pelo sistema de governança. - -Os titulares de átomos que delegam o seu poder de voto a outros validadores pagam uma comissão -ao validador delegado. A comissão pode ser definida por cada validador. - -### Incentivando Hackers - -A segurança do Cosmos Hub é uma função da segurança dos validadores subjacentes e da escolha -da delegação pelos delegados. A fim de incentivar a descoberta e notificação precoce de vulnerabilidades -encontradas, o Cosmos Hub incentiva os hackers a publicar exploits bem sucedidos através de uma transação -`ReportHackTx` que diz," Este validador foi hackeado. Por favor, envie recompensa para este endereço". -Depois de tal exploração, o validador e os delegados ficarão inativos, `HackPunishmentRatio` (PADRÃO DE 5%) -dos átomos de todos serão cortados, e`HackRewardRatio` (PADRÃO DE 5%) dos átomos de todos -serão recompensado com o endereço de recompensa do hacker. O validador deve recuperar os átomos -restantes usando sua chave de backup. - -Para evitar que esse recurso seja abusado para transferir átomos não invadidos, -a porção de átomos adquirido vs relativo de validadores e delegados antes e depois do `ReportHackTx` -permanecerá o mesmo, e o bounty do hacker irá incluir alguns átomos relativos, se houver. - -### Específicação de Governança - -O Cosmos Hub é operado por uma organização distribuída que requer um mecanismo de -governança bem definido para coordenar várias mudanças na blockchain, como parâmetros -variáveis do sistema, bem como atualizações de software e emendas constitucionais. - -Todos os validadores são responsáveis por votar em todas as propostas. -Não votar em uma proposta em tempo hábil resultará na desativação automática do -validador por um período de tempo denominado `AbsenteeismPenaltyPeriod` (PADRÃO DE 1 semana). - -Os delegados herdam automaticamente o voto do validador delegado. -Este voto pode ser anulado manualmente. Os átomos não ligados obtêm nenhum voto. - -Cada proposta requer um depósito de tokens de `MinimumProposalDeposit`, -que pode ser uma combinação de um ou mais tokens incluindo átomos. -Para cada proposta, os eleitores podem votar para receber o depósito. -Se mais da metade dos eleitores optarem por receber o depósito (por exemplo, porque a proposta era spam), -o depósito vai para a pool reserva, exceto os átomos que são queimados. - -Para cada proposta, os eleitores podem votar nas seguintes opições: - -- Sim -- Com Certeza -- Não -- Nunca -- Abstenção - -É necessário uma maioria estrita de votos Yea(Sim) ou YeaWithForce(Com certeza) -(ou votos Nay(Não) ou NayWithForce(Nunca)) para que a proposta seja decidida como aceita -(ou decidida como falha), mas 1/3+ pode vetar a decisão da maioria votando "Com certeza". -Quando uma maioria estrita é vetada, todos são punidos com a perda de `VetoPenaltyFeeBlocks` -(PADRÃO DE no valor de um dia de blocos) de taxas (exceto os impostos que não serão afetados), -e a parte que vetou a decisão da maioria será adicionalmente punida com a perda de `VetoPenaltyAtoms` -(PADRÃO DE 0.1%) de seus átomos. - -### Parâmetro de Mudança de Proposta - -Qualquer um dos parâmetros aqui definidos pode ser alterado com a aceitação -de um `ParameterChangeProposal`. - -### Texto da Proposta - -Todas as outras propostas, como uma proposta de atualização do protocolo, serão coordenadas através do genérico `TextProposal`. - -## Roteiro - -Veja [o Plano Cosmos](https://github.com/cosmos/cosmos/blob/master/PLAN.md). - -## Trabalho Relacionado - -Houve muitas inovações no consenso da blockchain e na escalabilidade nos últimos dois anos. -Esta seção fornece um breve levantamento de um seleto número das mais importantes. - -### Sistemas de Consenso - -#### Classic Byzantine Fault Tolerance - -Consenso na presença de participantes maliciosos é um problema que remonta ao início dos anos 1980, -quando Leslie Lamport cunhou a frase "falha bizantina" para se referir ao comportamento do processo -arbitrário que se desvia do comportamento pretendido, que contraste com uma "falha acidental", -em que um processo simplesmente falha. Soluções iniciais foram descobertas para redes síncronas onde -há um limite superior na latência da mensagem, embora o uso prático fosse limitado a ambientes altamente controlados, -como controladores de avião e datacenters sincronizados via relógios atômicos. -Não foi até o final dos anos 90 que a Practical Byzantine Fault Tolerance (PBFT) foi introduzida como -um eficiente algoritmo de consenso parcialmente síncrono capaz de tolerar até ⅓ de processos -comportando-se arbitrariamente. PBFT tornou-se o algoritmo padrão, gerando muitas variações, -incluindo mais recentemente uma criada pela IBM como parte de sua contribuição para a Hyperledger. - -O principal benefício do consenso Tendermint sobre PBFT é que o Tendermint tem uma estrutura -subjacente melhorada e simplificada, um dos quais é um resultado de adotar o paradigma blockchain. -Blocos Tendermint devem confirmar em ordem, o que evita a complexidade e sobrecarga de comunicação -associada a alteração de visão do PBFT's. No Cosmos e muitas outras criptomoedas, -não há necessidade de permitir o bloco <em>N+i</em> onde <em>i >= 1</em> se confirmar, -quando o próprio bloco <em>N</em> ainda não se confirmou. Se a largura de banda é a razão -pela qual o bloco <em>N</em> não se confirmou em uma zona do Cosmos, então isso não ajuda -a usar os votos de compartilhamento de largura de banda para blocos <em>N+i</em>. -Se uma partição de rede ou nós offline for a razão pela qual o bloco <em>N</em> não foi confirmado, -<em>N+i</em> não se comprometerá de qualquer maneira. - -Além disso, o lote de transações em blocos permite que o Merkle-hashing regule o estado da aplicação, -ao invés de resumos periódicos com esquemas de pontos de verificação como PBFT faz. -Isso permite confirmações de transações mais rápidas para clientes leves e uma comunicação mais rápida entre a blockchain. - -Tendermint Core também inclui muitas otimizações e recursos que vão acima e além do que é especificado no PBFT. -Por exemplo, os blocos propostos pelos validadores são divididos em partes, -Merkleized e inútilizados de tal forma que melhora o desempenho da transmissão -(ver LibSwift [\[19\]][19] para inspiração). Além disso, Tendermint Core não faz qualquer suposição sobre -a conectividade ponto-a-ponto, e funciona durante o tempo que a rede P2P está fracamente conectada. - -#### Participação delegada do BitShares - -Apesar de não serem os primeiros a implementar a prova-de-participação (Proof-of-Stake - PoS), -o BitShares [\[12\]][12] contribuiu consideravelmente para a pesquisa e adoção das blockchains que usam o PoS, -particularmente aqueles conhecidos como PoS "delegados". No BitShares, as partes interessadas elegem "testemunhas", -responsáveis por ordenar e confirmar transações e "delegados", responsáveis pela coordenação -de atualizações de software e alterações de parâmetros. Embora o BitShares atinja alto desempenho -(100k tx/s, 1s de latência) em condições ideais, ele está sujeito a ataques de duplo gasto por testemunhas -maliciosas que "forkem" a blockchain sem sofrer uma punição econômica explícita - ele sofre do problema -"nada a perder". O BitShares tenta suavizar o problema permitindo que as transações se refiram a -blocos-hashes recentes. Além disso, as partes interessadas podem remover ou substituir -testemunhas de má conduta diariamente, embora isso não faça nada para punir -explicitamente os ataques bem sucedidos de duplo gasto. - -#### Stellar - -Baseando-se em uma abordagem pioneira da Ripple, a Stellar [\[13\]][13] refinou um modelo do -Federated Byzantine Agreement em que os processos que participam do consenso não constituem -um conjunto fixo e globalmente conhecido. Em vez disso, cada nó de processo codifica uma ou mais -"fatias de quórum", cada uma constituindo um conjunto de processos confiáveis. Um "quórum" na -Stellar é definido como um conjunto de nós que contêm pelo menos uma fatia de quórum para cada -nó no conjunto, de modo que o acordo possa ser alcançado. - -A segurança do mecanismo Stellar baseia-se no pressuposto de que a intersecção de _qualquer_ dois -quóruns é não-vazia, enquanto a disponibilidade de um nó requer pelo menos uma das suas fatias de -quórum para consistir inteiramente de nós corretos, criando um troca externa entre o uso de grandes -ou pequenas fatias-quórum que podem ser difíceis de equilíbrar sem impor pressupostos significativos -sobre a confiança. Em última análise, os nós precisam, de alguma forma, escolher fatias de quórum adequadas -para que haja tolerância suficiente a falhas (ou qualquer "nó intacto" em geral, do qual muitos dos -resultados do trabalho dependem) e a única estratégia fornecida para garantir tal configuração é -hierárquica e similar ao Border Gateway Protocol (BGP), usado por ISPs de primeira linha na -internet para estabelecer tabelas de roteamento globais e usado pelos navegadores para gerenciar -certificados TLS; Ambos notórios por sua insegurança. - -A crítica sobre papel da Stellar nos sistemas PoS baseados em Tendermint é atenuada pela estratégia -de token descrita aqui, em que um novo tipo de token chamado _atom_ é emitido para representar -reivindicações para futuras porções de taxas e recompensas. A vantagem do PoS baseado em Tendermint, -portanto, é a sua relativa simplicidade, ao mesmo tempo que oferece garantias de segurança suficientes e prováveis. - -#### BitcoinNG - -O BitcoinNG é uma proposta de melhoria do Bitcoin que permitiria formas de escalabilidade vertical, -como o aumento do tamanho do bloco, sem as conseqüências econômicas negativas normalmente associadas a tal mudança, -como o impacto desproporcionalmente grande sobre os pequenos mineradores. Esta melhoria é conseguida separando -a eleição do líder da transmissão da transação: os líderes são eleitos pela primeira vez -por prova de trabalho(PoW) em "microblocos", e então são capazes de transmitir transações a -serem confirmadas até que um novo microbloco seja encontrado. Isso reduz os requisitos -de largura de banda necessários para vencer a corrida PoW, permitindo que os pequenos -mineiros possam competir mais justamente, e permitindo que as transações sejam confirmadas -com mais regularidade pelo último minerador para encontrar um micro-bloco. - -#### Casper - -Casper [\[16\]][16] é uma proposta de algoritmo de consenso PoS para o Ethereum. -Seu modo principal de operação é "consenso-por-aposta". Ao permitir que os validadores apostem -iterativamente em qual bloco eles acreditam que será confirmado na blockchain com base nas -outras apostas que eles têm visto até agora, a finalidade pode ser alcançada eventualmente. -[link](https://blog.ethereum.org/2015/12/28/understanding-serenity-part-2-casper/). Esta é uma área ativa -de pesquisa da equipe de Casper. O desafio está na construção de um mecanismo de apostas que pode ser -comprovado como uma estratégia evolutivamente estável. O principal benefício da Casper em relação à -Tendermint pode ser a oferta de "disponibilidade sobre a consistência" - consenso não requer -um quórum +⅔ de poder de voto - talvez ao custo de velocidade de confirmação ou complexidade de implementação. - -### Escala Horizontal - -#### Protocolo Interledger - -O Protocolo Interledger [\[14\]][14] não é estritamente uma solução de escalabilidade. -Ele fornece uma interoperabilidade ad hoc entre diferentes sistemas de ledger através de uma rede -de relações bilaterais livremente acopladas. Tal como a Lightning Network, a finalidade do -ILP é facilitar pagamentos, mas focaliza especificamente pagamentos em diferentes tipos de ledger, -estendendo o mecanismo de transações atômicas para incluir não apenas hash-locks, mas também um -quórum de notários (chamado de Atomic Transport Protocol). O último mecanismo para reforçar a -atomicidade em transacções entre-ledger é semelhante ao mecanismo SPV do cliente leve do Tendermint, -então uma ilustração da distinção entre ILP e Cosmos/IBC é garantida, e fornecida abaixo. - -1. Os notários de um conector em ILP não suportam mudanças de consentimento, e não permitem uma - pesagem flexível entre notários. Por outro lado, o IBC é projetado especificamente para blockchains, - onde os validadores podem ter diferentes pesos, e onde o consentimento pode mudar ao longo da cadeia de blocos. - -2. Como na Lightning Network, o receptor do pagamento em ILP deve estar on-line para enviar - uma confirmação de volta ao remetente. Em uma transferência de token sobre IBC, o conjunto - de validadores da blockchain do receptor é responsável por fornecer a confirmação, não o usuário receptor. - -3. A diferença mais notável é que os conectores do ILP não são responsáveis ou mantêm o estado - autoritário sobre os pagamentos, enquanto que no Cosmos, os validadores de um hub são a autoridade - do estado das transferências de tokens do IBC, bem como a autoridade da quantidade de tokens - mantidos por cada zona (mas não a quantidade de tokens mantidos por cada conta dentro de uma zona). - Esta é a inovação fundamental que permite a tranferência assimétrica segura de tokens de zona para - zona; O conector analógico do ILP no Cosmos é uma persistente e maximamente segura ledger de blockchain, o Cosmos Hub. - -4. Os pagamentos entre contas no ILP precisam ser suportados por uma ordem de compra/venda, uma - vez que não há transferência assimétrica de moedas de um ledger para outro, apenas a transferência - de valor ou equivalentes de mercado. - -#### Sidechains - -Sidechains [\[15\]][15] são um mecanismo proposto para dimensionar a rede Bitcoin através de -blockchains alternativas que são "atreladas" para a blockchain do Bitcoin. As Sidechains -permitem que bitcoins se movam efetivamente da blockchain do Bitcoin para a sidechain e retornarem, -e permitem a experimentação em novos recursos na sidechain. Como no Cosmos Hub, a sidechain e -Bitcoin servem como clientes leves uns dos outros, usando provas SPV para determinar quando as moedas -devem ser transferidas para a cadeia lateral e retornarem. Claro, como o Bitcoin usa PoW, sidechains -centradas em torno do Bitcoin sofrem dos muitos problemas e riscos do PoW como um mecanismo de consenso. -Além disso, esta é uma solução Bitcoin-maximalista que não suporta nativamente uma variedade de tokens e -topologia de rede entre-zona como o Cosmos faz. Dito isto, o mecanismo de núcleo bidirecional atrelado é, -em princípio, o mesmo que o empregado pela rede Cosmos. - -#### Esforços de Escalabilidade do Ethereum - -Ethereum está atualmente pesquisando uma série de estratégias diferentes para fragmentar o -estado da blockchain do Ethereum para atender às necessidades de escalabilidade. -Esses esforços têm como objetivo manter a camada de abstração oferecida pela atual -Ethereum Virtual Machine através do espaço de estado compartilhado. Vários esforços de -pesquisa estão em andamento neste momento. [\[18\]][18][\[22\]][22] - -##### Cosmos vs Ethereum 2.0 Mauve - -Cosmos e Ethereum 2.0 Mauve [\[22\]][22] tem diferentes objetivos de projeto. - -- Cosmos é especificamente sobre tokens. Malva é sobre escalonamento de computação geral. -- O Cosmos não está ligado ao EVM, por isso mesmo VMs diferentes podem interoperar. -- Cosmos permite que o criador da zona determine quem valida a zona. -- Qualquer pessoa pode iniciar uma nova zona no Cosmos (a menos que a governança decida o contrário). -- O hub isola falhas de zonas de modo que tokens invariantes sejam preservados. - -### Escala Geral - -#### Lightning Network - -A Lightning Network é uma proposta de rede de transferência de token operando em uma camada acima -da blockchain do Bitcoin (e outras blockchains públicas), permitindo a melhoria de muitas ordens -de magnitude no processamento de transações movendo a maioria das transações fora da ledger de consenso -para o chamado "Canais de pagamento". Isso é possível graças a scripts de criptomoedas em cadeia, -que permitem que as partes entrem em contratos estatais bilaterais onde o estado pode ser atualizado -compartilhando assinaturas digitais, e os contratos podem ser fechados definitivamente publicando -evidências na blockchain, um mecanismo primeiramente popularizado por trocas atômicas de -cross-chains(cadeias cruzadas). Ao abrir canais de pagamento com muitas partes, os participantes -da Lightning Network podem se tornar pontos focais para encaminhar os pagamentos de outros, -levando a uma rede de canais de pagamento totalmente conectada, ao custo do capital estar ligado aos canais de pagamento. - -Enquanto a Lightning Network também pode facilmente se estender através de várias blockchains independentes -para permitir a transferência de _value_ através de um mercado de câmbio, não pode ser usado para -transferir assimetricamente _tokens_ de uma blockchain para outra. O principal benefício da rede Cosmos -descrita aqui é permitir tais transferências diretas de tokens. Dito isto, esperamos que os canais de -pagamento e a Lightning Network sejam amplamente adotados juntamente com nosso mecanismo de transferência -de token, por razões de economia de custos e privacidade. - -#### Segregated Witness - -Segregated Witness é uma proposta de melhoria do Bitcoin -[link](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) que visa aumentar em 2X ou 3X a -taxa de transferência por bloco, ao mesmo tempo que faz a sincronização de blocos ser mais rapida para -novos nós. O brilho desta solução é de como ele funciona dentro das limitações do protocolo atual do Bitcoin -e permite uma atualização de soft-fork (ou seja, os clientes com versões mais antigas do software -continuarão funcionando após a atualização). O Tendermint, sendo um novo protocolo, não tem restrições -de projeto, por isso tem prioridades diferentes de escalonamento. Sobretudo, o Tendermint usa um algoritmo -de rodízio BFT baseado em assinaturas criptográficas em vez de mineração, o que trivialmente permite escalonamento -horizontal através de múltiplas blockchains paralelas, enquanto que os regulares e mais frequentes blocos confirmam -a escala vertical também. - -<hr/> - -## Apêndice - -### Responsabilidade de Fork - -Um protocolo de consenso bem projetado deve fornecer algumas garantias no caso da capacidade de -tolerância ser excedida e o consenso falhar. Isto é especialmente necessário nos sistemas econômicos, -onde o comportamento Bizantino pode ter recompensa financeira substancial. A -garantia maisimportante é uma forma de _fork-accountability_, onde os processos que -fizeram com que o consenso falhasse (ou seja, clientes do protocolo -motivados para aceitar valores diferentes - um fork) podem ser identificados e punidos de acordo com as -regras do protocolo , Ou, possivelmente, o sistema jurídico. Quando o sistema jurídico não é confiável -ou é excessivamente caro para suplicar, os validadores podem ser forçados a fazerem depósitos de segurança -para participar, e esses depósitos podem ser revogados ou cortados, quando um comportamento malicioso é detectado [\[10\]][10]. - -Observe que isso é diferente do Bitcoin, onde o fork é uma ocorrência regular devido à assincronia de -rede e à natureza probabilística de encontrar colisões de hash parciais. Uma vez que, em muitos casos, -um fork malicioso é indistinguível de um fork devido à assincronia, o Bitcoin não pode implementar de -forma confiável a responsabilidade de um fork, com exceção do custo implícito pago por mineradores que -tem a oportunidade de minerarem um bloco órfão. - -### Consenso Tendermint - -Chamamos as fases de votação de _PreVote_ e _PreCommit_. Um voto pode ser para um bloco em particular ou -para _Nil_. Chamamos uma coleção de +⅔ PreVotes para um único bloco na mesma rodada de um _Polka_, e uma -coleção de +⅔ PreCommits para um único bloco na mesma rodada de um _Commit_. Se +⅔ PreCommit para Nil na -mesma rodada, eles passam para a próxima rodada. - -Observe que o determinismo estrito no protocolo incorre em uma suposição de sincronia fraca, pois os líderes -com falhas devem ser detectados e ignorados. Assim, os validadores aguardam algum tempo, _TimeoutPropose_, -antes de Prevote Nil, e o valor de TimeoutPropose aumenta a cada rodada. A progressão através do -resto de uma rodada é totalmente assincrôna, onde o progresso é feito somente quando um validador -ouve de +⅔ da rede. Na prática, seria necessário um adversário extremamente forte para impedir -indefinidamente a suposição de sincronia fraca (fazendo com que o consenso deixasse de confirmar um bloco), -e isso pode ser ainda mais difícil usando valores randomizados de TimeoutPropose em cada validador. - -Um conjunto adicional de restrições, ou Locking Rules(Regras de bloqueio), garante que a rede acabará -por confirmar apenas um bloco em cada altura. Qualquer tentativa maliciosa de confirmar de causar um -bloco a ser confirmado a uma determinada altura pode ser identificada. Primeiro, um PreCommit para um -bloco deve vir com justificação, na forma de um Polka para esse bloco. Se o validador já tiver PreCommit -um bloco na rodada <em>R*1</em>, nós dizemos que eles estão \_locked* nesse bloco, e o Polka usado -para justificar o novo PreCommit na rodada <em>R_2</em> deve vir de uma rodada <em>R_polka</em> -onde <em>R_1 < R_polka <= R_2</em>. Em segundo lugar, os validadores devem propor e/ou pré-votar -o bloco que eles estão travados. Juntas, essas condições garantem que um validador não PreCommit -sem evidência suficiente como justificativa, e que os validadores que já têm PreCommit não podem -contribuir para a evidência de PreCommit algo mais. Isso garante a segurança e a vivacidade do algoritmo de consenso. - -Os detalhes completos do protocolo são descritos -[aqui](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - -### Clientes Leves do Tendermint - -A necessidade de sincronizar todos os cabeçalhos de bloco é eliminada no Tendermint-PoS, como por exemplo -a existência de uma cadeia alternativa (um fork) significando que ⅓+ do stake ligado pode ser reduzido. -Naturalmente, a partir que dividir requer que _someone_ compartilhe evidência de um fork, clientes leves -devem armazenar qualquer bloco-hash comprometido que eles vêem. Além disso, os clientes leves podem -periodicamente ficarem sincronizados com as alterações no conjunto de validadores, para evitar -[ataques de longo alcance](#preventing-long-range-attacks) (mas outras soluções são possíveis). - -Em espírito semelhante do Ethereum, o Tendermint permite que os aplicativos incorporem um hash de raiz -Merkle global em cada bloco, permitindo verifícações fáceis de consultas de estado para fins como saldos -de contas, o valor armazenado em um contrato ou a existência de saída de uma transação não gasta, -dependendo da natureza da aplicação. - -### Prevenção de ataques de longo alcance - -Assumindo uma coleção suficientemente elástica de redes de difusão e um conjunto de validador -estático, qualquer fork na blockchain pode ser detectado e os depósitos dos validadores ofensivos cortados. -Esta inovação, sugerida pela primeira vez por Vitalik Buterin no início de 2014, resolve o problema do "nada a perder" de outras -criptomoedas de PoW (ver [Trabalho Relacionado](#related-work)). No entanto, uma vez que os conjuntos de -validadores devem ser capazes de mudar, durante um longo período de tempo, os validadores originais podem -tornar-se não ligados e, portanto, seriam livres para criar uma nova cadeia a partir do bloco gênese, -não incorrendo nenhum custo, visto que eles não tem depósitos trancados. Este ataque veio a ser conhecido -como Ataque de Longo Alcance (Long Range Attack - LRA), em contraste com um Ataque de Curto Alcance, -onde os validadores que estão atualmente ligados causam um fork e são, portanto, puníveis -(assumindo um algoritimo BFT de fork-responsável como o consenso Tendermint). -Ataques de longo alcance são muitas vezes pensados para serem um golpe crítico para o PoW. - -Felizmente, o LRA pode ser atenuado da seguinte forma. Em primeiro lugar, para que um validador se -desatar (assim recuperando seu depósito colateral e não mais ganhando taxas para participar no consenso), -o depósito deve ser tornado intransferível por um período de tempo conhecido como o "unbonding period" -(período de desatamento), que pode ser na ordem de semanas ou meses. Em segundo lugar, para um cliente -leve ser seguro, a primeira vez que ele se conecta à rede, ele deve verificar um hash de bloqueio recente -contra uma fonte confiável ou, preferencialmente, várias fontes. Esta condição é por vezes referida como -"subjetividade fraca". Finalmente, para permanecer seguro, ele deve sincronizar com o mais recente -validador definido, pelo menos, tão frequentemente quanto a duração do período de desatamento. -Isso garante que o cliente leve saiba sobre as alterações no conjunto de validação definido antes de -um validador não ter mais o seu capital ligado e, portanto, não mais em jogo, o que permitiria enganar -o cliente, executando um ataque de longo alcance, criando novos blocos re-começando em uma altura -a qual foi ligado (assumindo que tem controle de muitas das primeiras chaves privadas). - -Note que superar o LRA desta forma requer uma revisão do modelo de segurança original do PoW. No PoW, -presume-se que um cliente leve pode sincronizar com a altura atual do bloco gênese confiável a qualquer -momento simplesmente processando o PoW em cada cabeçalho de bloco. Para superar o LRA, entretanto, -exigimos que um cliente leve entre em linha com alguma regularidade para rastrear mudanças no conjunto -de validadores e que, na primeira vez em que eles fiquem on-line, eles devem ser particularmente cuidadosos -para autenticar o que ouvem da rede contra fontes confiáveis . Naturalmente, este último requisito é -semelhante ao do Bitcoin, onde o protocolo e o software também devem ser obtidos a partir de uma fonte confiável. - -O método acima para prevenir LRA é bem adequado para validadores e nós completos de uma blockchain alimentada -por Tendermint porque estes nós são destinados a permanecerem conectados à rede. O método também é adequado -para clientes leves que podem ser esperados para sincronizar com a rede com freqüência. No entanto, para -os clientes leves que não se espera ter acesso frequente à Internet ou à rede da blockchain, ainda pode -ser utilizada outra solução para superar o LRA. Os detentores de tokens não validadores podem publicar -os seus tokens como colaterais com um período de não ligação muito longo (por exemplo, muito mais longo -do que o período de não ligação para validadores) e servir clientes leves com um método secundário de -atestar a validade dos blocos atuais e hashes de blocos passados. Embora esses tokens não contam para a -segurança do consenso da blockchain, eles podem fornecer fortes garantias para clientes leves. Se a -consulta histórica de hash de blocos fosse suportada no Ethereum, qualquer pessoa poderia vincular -seus tokens em um contrato inteligente projetado especialmente para isso e fornecer serviços de -comprovação de pagamentos, efetivamente criando um mercado para a segurança contra LRA de cliente leve. - -### Superando Forks e Ataques de Censura - -Devido à definição de uma confimação de bloco, qualquer coalizão de poder de voto ⅓+ pode interromper a -blockchain ficando off-line ou não transmitir os seus votos. Tal coalizão também pode censurar transações -particulares rejeitando blocos que incluem essas transações, embora isso resultaria em uma proporção -significativa de propostas de blocos a serem rejeitadas, o que iria retardar a taxa de blocos -confirmados da blockchain, reduzindo sua utilidade e valor. A coalizão mal-intencionada também pode transmitir -votos em um fio de modo a triturar os blocos confirmados da blockchain para quase parar, ou se envolver em -qualquer combinação desses ataques. Finalmente, isso pode fazer com que a cadeia de blocos "forke" (bifurque), -por dupla assinatura ou violação as regras de bloqueio. - -Se um adversário globalmente ativo também estivesse envolvido, poderia dividir a rede de tal maneira que -possa parecer que o subconjunto errado de validadores era responsável pela desaceleração. Esta não é apenas -uma limitação do Tendermint, mas sim uma limitação de todos os protocolos de consenso cuja -rede é potencialmente controlada por um adversário ativo. - -Para estes tipos de ataques, um subconjunto de validadores deve coordenar através de meios externos -para assinar um proposta de reorganização que escolhe um fork (e qualquer prova disso) e o -subconjunto inicial de validadores com suas assinaturas. Os validadores que assinam tal -proposta de reorganização deixam seu colateral em todos os outros forks. Os clientes -devem verificar as assinaturas na proposta de reorganização, verificar qualquer -evidência e fazer um julgamento ou solicitar ao usuário final uma decisão. Por exemplo, -uma carteira para celular um aplicativo que pode alertar o usuário com um aviso de segurança, -enquanto um refrigerador pode aceitar qualquer proposta de reorganização assinada por -\+½ dos validadores originais por poder de voto. - -Nenhum algoritmo não-sincrônico tolerante a falhas Bizantino pode chegar a um consenso quando ⅓+ -de poder de voto for desonesto, mas um fork supõe que ⅓+ do poder de voto já foram desonestos por -dupla assinatura ou bloqueio de mudança sem justificativa. Portanto, assinar a proposta de -reorganização é um problema de coordenação que não pode ser resolvido por qualquer protocolo -não-sincronico (isto é, automaticamente e sem fazer suposições sobre a confiabilidade da rede subjacente). -Por enquanto, deixamos o problema da coordenação da proposta de reorganização para a coordenação -humana através do consenso social na mídia na internet. Os validadores devem ter cuidado para garantir -que não haja partições de rede remanescentes antes de assinar uma proposta de reorganização, -para evitar situações em que duas propostas de reorganização em conflito sejam assinadas. - -Assumindo que o meio de coordenação é externo e o protocolo é robusto, resulta-se que os forks são -uma preocupação menor do que os ataques de censura. - -Além de forks e censura, que exigem ⅓+ poder de votação Bizantina, uma coalizão de +⅔ poder de -voto pode ser pratica arbitrária, estado inválido. Esta é a característica de qualquer sistema -de consenso (BFT). Ao contrário da dupla assinatura, que cria forks com provas facilmente -verificáveis, a detecção de obrigatoriedade de um estado inválido requer que os pares não -validadores verifiquem blocos inteiros, o que implica que eles mantêm uma cópia local do estado -e executam cada transação, computando a raiz de estado de forma independente para eles mesmos. -Uma vez detectado, a única maneira de lidar com essa falha é através do consenso social. -Por exemplo, em situações em que o Bitcoin falhou, seja por causa de bugs de software -(como em março de 2013), ou praticar um estado inválido devido ao comportamento Bizantino -dos mineradores (como em julho de 2015), a comunidade bem conectada de negócios, desenvolvedores, -mineradores e outras organizações estabeleceu um consenso social sobre quais ações manuais se -faziam necessárias para curar a rede. Além disso, uma vez que se pode esperar que os validadores -de uma cadeia de blocos de Tendermint sejam identificáveis, o compromisso de um estado inválido -pode até ser punido por lei ou por alguma jurisprudência externa, se desejado. - -### Especificação TMSP - -TMSP consiste em 3 tipos de mensagens primárias que são entregues do núcleo para o aplicativo. -O aplicativo responde com mensagens de resposta correspondentes. - -A mensagem `AppendTx` é o cavalo de trabalho da aplicação. Cada transação na blockchain -é entregue com esta mensagem. O aplicativo precisa validar cada transação recebida com a -mensagem AppendTx contra o estado atual, o protocolo de aplicativo e as credenciais -criptográficas da transação. Uma transação validada precisa atualizar o estado do -aplicativo - vinculando um valor a um armazenamento de valores chave ou atualizando o banco de dados UTXO. - -A mensagem `CheckTx` é semelhante à AppendTx, mas é apenas para validar transações. O mempool do -Tendermint Core primeiro verifica a validade de uma transação com o CheckTx e apenas relata -transações válidas para seus pares. Os aplicativos podem verificar um nonce incremental na transação -e retornar um erro em CheckTx se o nonce é antigo. - -A mensagem `Commit` é usada para calcular uma obrigação criptográfica com o estado atual da aplicação, -para ser colocada no próximo cabeçalho do bloco. Isso tem algumas propriedades úteis. Inconsistências -na atualização desse estado agora aparecerão como forks do blockchain que captura uma classe inteira -de erros de programação. Isso também simplifica o desenvolvimento de clientes leves e seguros, -já que as provas de Merkle-hash podem ser provadas verificando o hash de blocos, -e o hash de blocos é assinado por um quórum de validadores (por poder de voto). - -Mensagens TMSP adicionais permitem que o aplicativo acompanhe e altere o conjunto -de validadores e que o aplicativo receba as informações do bloco, como a altura e os votos de confirmação. - -Pedidos/respostas TMSP são simples mensagens Protobuf. -Confira o [arquivo do esquema](https://github.com/tendermint/abci/blob/master/types/types.proto). - -##### AppendTx - -- **Arguments**: - - `Data ([]byte)`: Os bytes de transação solicitada -- **Returns**: - - `Code (uint32)`: Código de resposta - - `Data ([]byte)`: Bytes de resultado, se houver - - `Log (string)`: Debug ou mensagem de erro -- **Usage**:<br/> - Acrescentar e executar uma transação. Se a transação for válida, - CodeType.OK - -##### CheckTx - -- **Arguments**: - - `Data ([]byte)`: Os bytes de transação solicitados -- **Returns**: - - `Code (uint32)`: Código de resposta - - `Data ([]byte)`: Bytes de resultado, se houver - - `Log (string)`: Debug ou mensagem de erro -- **Usage**:<br/> - Validar uma transação. Esta mensagem não deve mutar o estado. - As transações são primeiro executadas através do CheckTx antes da transmissão para os pares na camada mempool. - Você pode fazer o CheckTx semi-stateful e limpar o estado após `Commit` ou - `BeginBlock`, - para permitir sequências dependentes de transações no mesmo bloco. - -##### Commit - -- **Returns**: - - `Data ([]byte)`: O hash Merkle raiz - - `Log (string)`: Debug ou erro de mensagem -- **Usage**:<br/> - Retorna um hash Merkle raiz do estado da aplicação. - -##### Query - -- **Arguments**: - - `Data ([]byte)`: Os bytes de solicitação consultada -- **Returns**: - - `Code (uint32)`: Código de resposta - - `Data ([]byte)`: Os bytes de resposta consultada - - `Log (string)`: Debug ou erro de mensagem - -##### Flush - -- **Usage**:<br/> - Limpar a fila de resposta. Aplicações que implementam `types.Application` - não precisa implementar esta mensagem - é tratada pelo projeto. - -##### Info - -- **Returns**: - - `Data ([]byte)`: Os bytes de informação -- **Usage**:<br/> - Retorna informações sobre o estado da aplicação. Aplicação específicão. - -##### SetOption - -- **Arguments**: - - `Key (string)`: Chave para definir - - `Value (string)`: Valor a definir para a chave -- **Returns**: - - `Log (string)`: Debug ou mensagem de erro -- **Usage**:<br/> - Define as opções do aplicativo. Exemplo Key="mode", Value="mempool" para uma conexão mempool - , ou Key="mode", Value="consensus" para uma conexão de consenso. - Outras opções são específicas da aplicação. - -##### InitChain - -- **Arguments**: - - `Validators ([]Validator)`: validadores de genesis iniciais -- **Usage**:<br/> - Chamado uma vez na genesis - -##### BeginBlock - -- **Arguments**: - - `Height (uint64)`: A altura do bloco que está começando -- **Usage**:<br/> - Sinaliza o início de um novo bloco. Chamado antes de qualquer AppendTxs. - -##### EndBlock - -- **Arguments**: - - `Height (uint64)`: A altura do bloco que terminou -- **Returns**: - - `Validators ([]Validator)`: Mudança de validadores com novos poderes de voto (0 - para remover) -- **Usage**:<br/> - Sinaliza o fim de um bloco. Chamado antes de cada Commit após todas as - transações - -Veja [o repositório TMSP](https://github.com/tendermint/abci) para mais detalhes. - -### Reconhecimento de entrega de pacotes IBC - -Há várias razões pelas quais um remetente pode querer o reconhecimento da entrega de um pacote -pela cadeia de recebimento. Por exemplo, o remetente pode não saber o status da cadeia de -destino, se for esperado que esteja com defeito. Ou, o remetente pode querer impor um tempo -limite no pacote (com o campo `MaxHeight`), enquanto qualquer cadeia de destino pode sofrer -de um ataque de negação de serviço com um aumento repentino no número de pacotes de entrada. - -Nesses casos, o remetente pode exigir confirmação de entrega configurando o status -do pacote inicial como `AckPending`. Em seguida, é a responsabilidade da -cadeia receptora confirmar a entrega, incluindo uma abreviada `IBCPacket` no app Merkle hash. - -![Figura da Zone1, Zone2, e Hub IBC com -reconhecimento](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack.png) - -Primeiro, um `IBCBlockCommit` e`IBCPacketTx` são postados no "Hub" que prova -a existência de um `IBCPacket` na "Zone1". Digamos que `IBCPacketTx` tem o seguinte valor: - -- `FromChainID`: "Zone1" -- `FromBlockHeight`: 100 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 (say) - - `Status`: `AckPending` - - `Type`: "moeda" - - `MaxHeight`: 350 (Dizer que "Hub" está atualmente na altura 300) - - `Payload`: <Os bytes de uma carga paga de "moeda"> - -Em seguida, um `IBCBlockCommit` e `IBCPacketTx` são publicados na "Zone2" que comprova -a existência de um `IBCPacket` em "Hub". Digamos que `IBCPacketTx` tem o seguinte valor: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 300 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckPending` - - `Type`: "moeda" - - `MaxHeight`: 350 - - `Payload`: <Os mesmos bytes de uma carga paga de "moeda"> - -Em seguida, "Zone2" deve incluir em seu app-hash um pacote abreviado que mostra o novo -status de `AckSent`. Um `IBCBlockCommit` e `IBCPacketTx` são colocados de volta no "Hub" -que comprova a existência de um `IBCPacket` abreviado na "Zone2". Digamos que `IBCPacketTx` tem o seguinte valor: - -- `FromChainID`: "Zone2" -- `FromBlockHeight`: 400 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckSent` - - `Type`: "moeda" - - `MaxHeight`: 350 - - `PayloadHash`: <Os bytes de hash da mesma carga paga de "moeda"> - -Finalmente, "Hub" deve atualizar o status do pacote de `AckPending` para`AckReceived`. -A evidência desse novo status finalizado deve voltar a "Zone2". Digamos que `IBCPacketTx` tem o seguinte valor: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 301 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckReceived` - - `Type`: "moeda" - - `MaxHeight`: 350 - - `PayloadHash`: <Os bytes de hash da mesma carga paga de "moeda"> - -Enquanto isso, "Zone1" pode assumir de maneira otimista a entrega bem-sucedida de um pacote -de "moeda", a menos que provas em contrário sejam comprovadas em "Hub". No exemplo acima, -se "Hub" não tivesse recebido um status `AckSent` de "Zone2" pelo bloco 350, ele teria -definido o status automaticamente para `Timeout`. Essa evidência de um tempo limite pode -ser postada novamente na "Zone1", e quaisquer tokens podem ser retornados. - -![Figura da Zone1, Zone2, e Hub IBC com reconhecimento e -timeout](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack_timeout.png) - -### Árvore Merkle e Especificação de Prova - -Existem dois tipos de árvores Merkle suportadas no ecossistema Tendermint / Cosmos: A Árvore Simples e a Árvore IAVL+. - -#### Árvore Simples - -A Árvore Simples é uma árvore Merkle para uma lista estática de elementos. Se o número de -itens não for um poder de dois, algumas folhas estarão em níveis diferentes. Árvore Simples -tenta manter ambos os lados da árvore da mesma altura, mas a esquerda pode ter um maior. -Esta árvore Merkle é usada para Merkle-lizar as transações de um bloco, e os elementos de -nível superior da raiz do estado do aplicativo. - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - - Uma ÁrvoreSimples com sete elementos - -#### Árvore IAVL+ - -O objetivo da estrutura de dados IAVL+ é fornecer armazenamento persistente para pares de valores-chave -no estado do aplicativo, de modo que um hash determinista de raiz Merkle possa ser calculado -eficientemente. A árvore é balanceada usando uma variante do [algoritmo AVL](https://en.wikipedia.org/wiki/AVL_tree), e todas as operações são O(log(n)). - -Em uma árvore AVL, as alturas das duas subárvores filhas de qualquer nó diferem por no máximo um. -Sempre que esta condição for violada após uma atualização, a árvore é rebalanceada criando O(log(n)) -novos nós que apontam para nós não modificados da árvore antiga. No algoritmo AVL original, os nós -internos também podem conter pares de valores-chave. O algoritmo AVL + (observe o sinal de adição) -modifica o algoritmo AVL para manter todos os valores em folha de nós, enquanto -usando apenas nós de ramo para armazenar chaves. Isso simplifica o algoritmo, mantendo a trilha hash merkle curta. - -A Árvore AVL + é análoga à Ethereum [Patricia tries](https://en.wikipedia.org/wiki/Radix_tree). -Há compensações. Chaves não precisam ser hasheadas antes da inserção em árvores IAVL+, portanto, -isso fornece iteração mais rápida ordenada no espaço-chave que pode beneficiar algumas aplicações. -A lógica é mais simples de implementar, requerendo apenas dois tipos de nós - nós internos e nós de folhas. -A prova de Merkle é em média mais curta, sendo uma árvore binária equilibrada. Por outro lado, -a raiz Merkle de uma árvore IAVL+ depende da ordem das atualizações. - -Iremos apoiar outras árvores Merkle eficientes, como Patricia Trie, da Ethereum, quando a variante binária estiver disponível. - -### Tipos de Transação - -Na implementação canônica, as transações são transmitidas para o aplicativo Cosmos hub através da interface TMSP. - -O Cosmos Hub aceitará uma série de tipos de transações primárias, incluindo `SendTx`, -`BondTx`, `UnbondTx`, `ReportHackTx`, `SlashTx`, `BurnAtomTx`, `ProposalCreateTx` e `ProposalVoteTx`, -que são relativamente auto-explicativas e será documentado em uma futura revisão deste artigo. -Aqui documentamos os dois principais tipos de transação para IBC: `IBCBlockCommitTx` e `IBCPacketTx`. - -#### IBCBlockCommitTx - -Uma transação `IBCBlockCommitTx` é composta de: - -- `ChainID (string)`: O ID da blockchain -- `BlockHash ([]byte)`: Os bytes de hash de bloco, a raiz Merkle que inclui o app-hash -- `BlockPartsHeader (PartSetHeader)`: Os bytes de cabeçalho do conjunto de blocos, - apenas necessários para verificar assinaturas de voto -- `BlockHeight (int)`: A altura do commit -- `BlockRound (int)`: A rodada do commit -- `Commit ([]Vote)`: O +⅔ Tendermint `Precommit` de votos que compõem um bloco -- `ValidatorsHash ([]byte)`: O hash da raiz da árvore-Merkle do novo conjunto de validadores -- `ValidatorsHashProof (SimpleProof)`: Uma ÁrvoreSimples da prova-Merkle para provar o - `ValidatorsHash` contra o `BlockHash` -- `AppHash ([]byte)`: Um hash da raiz da árvore-Merkle da Árvore IAVL do estado de aplicação -- `AppHashProof (SimpleProof)`: Uma ÁrvoreSimples da prova-Merkle para provar o - `AppHash` contra o `BlockHash` - -#### IBCPacketTx - -Um `IBCPacket` é composto de: - -- `Header (IBCPacketHeader)`: O cabeçalho do pacote -- `Payload ([]byte)`: Os bytes da carga paga do pacote. _Optional_ -- `PayloadHash ([]byte)`: O hash para os bytes do pacote. _Optional_ - -Qualquer um dos `Payload` ou `PayloadHash` deve estar presente. O hash de um `IBCPacket` -é uma raiz Merkle simples dos dois itens, `Header` e `Payload`. Um `IBCPacket` sem a carga completa -é chamado de _abbreviated packet_. - -Um `IBCPacketHeader` é composto de: - -- `SrcChainID (string)`: O ID da blockchain fonte -- `DstChainID (string)`: O ID da blockchain destino -- `Number (int)`: Um número exclusivo para todos os pacotes -- `Status (enum)`: Pode ser um `AckPending`, `AckSent`, `AckReceived`, - `NoAck`, ou `Timeout` -- `Type (string)`: Os tipos são dependentes da aplicação. Cosmos reserva-se ao tipo de pacote "moeda" -- `MaxHeight (int)`: Se status não for `NoAckWanted` ou `AckReceived` por essa altura, o status se tornará `Timeout`. _Opcional_ - -Uma transação `IBCPacketTx` é composta de: - -- `FromChainID (string)`: O ID da blockchain que está fornecendo este pacote; Não necessariamente a fonte -- `FromBlockHeight (int)`: A altura da blockchain na qual o seguinte pacote é incluído (Merkle-izado) no hash da blockchain de origem -- `Packet (IBCPacket)`: Um pacote de dados, cujo estado pode ser um - `AckPending`, `AckSent`, `AckReceived`, `NoAck`, ou `Timeout` -- `PacketProof (IAVLProof)`: Uma prova-Merkle da Árvore IAVL para para provar o hash do pacote contra o \`AppHash' da cadeia de origem em determinada altura - -A seqüência para enviar um pacote da "Zone1" para a "Zone2" através do "Hub" é mostrada em {Figure X}. -Primeiro, um `IBCPacketTx` prova ao "Hub" que o pacote está incluído no estado da aplicação de "Zone1". -Em seguida, outro `IBCPacketTx` prova a "Zone2" que o pacote está incluído no estado da aplicação "Hub". -Durante esse procedimento, os campos `IBCPacket` são idênticos: o `SrcChainID` é sempre "Zone1", -e o `DstChainID` é sempre" Zone2 ". - -O `PacketProof` deve ter o caminho correto da prova-Merkle, da seguinte maneira: - - IBC/<SrcChainID>/<DstChainID>/<Number> - -Quando "Zone1" quer enviar um pacote para "Zone2" através do "Hub", os dados de `IBCPacket` -são idênticos se o pacote é Merkle-izado em "Zone1", no "Hub" ou "Zone2". O único campo mutável -é `Status` para acompanhar a entrega, conforme mostrado abaixo. - -## Agradecimentos - -Agradecemos aos nossos amigos e colegas por sua ajuda na conceituação, revisão e apoio no nosso trabalho com Tendermint e Cosmos. - -- [Zaki Manian](https://github.com/zmanian) da - [SkuChain](http://www.skuchain.com/) forneceu muita ajuda na formatação e redacção, especialmente sob a seção TMSP -- [Jehan Tremback](https://github.com/jtremback) da Althea and Dustin Byington - por ajudar com iterações iniciais -- [Andrew Miller](https://soc1024.com/) da [Honey - Badger](https://eprint.iacr.org/2016/199) pelo feedback sobre consenso -- [Greg Slepak](https://fixingtao.com/) pelo feedback sobre consenso e redação -- Também agradecemos ao [Bill Gleim](https://github.com/gleim) e [Seunghwan - Han](http://www.seunghwanhan.com) por várias contribuições. -- [Pedro Augusto](https://github.com/ShooterXD) pela tradução para - Português - -## Citações - -- [1] Bitcoin: <https://bitcoin.org/bitcoin.pdf> -- [2] ZeroCash: <http://zerocash-project.org/paper> -- [3] Ethereum: <https://github.com/ethereum/wiki/wiki/White-Paper> -- [4] TheDAO: <https://download.slock.it/public/DAO/WhitePaper.pdf> -- [5] Segregated Witness: <https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki> -- [6] BitcoinNG: <https://arxiv.org/pdf/1510.02037v2.pdf> -- [7] Lightning Network: <https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf> -- [8] Tendermint: <https://github.com/tendermint/tendermint/wiki> -- [9] FLP Impossibility: <https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf> -- [10] Slasher: <https://blog.ethereum.org/2014/01/15/slasher-a-punitive-proof-of-stake-algorithm/> -- [11] PBFT: <http://pmg.csail.mit.edu/papers/osdi99.pdf> -- [12] BitShares: <https://bitshares.org/technology/delegated-proof-of-stake-consensus/> -- [13] Stellar: <https://www.stellar.org/papers/stellar-consensus-protocol.pdf> -- [14] Interledger: <https://interledger.org/rfcs/0001-interledger-architecture/> -- [15] Sidechains: <https://blockstream.com/sidechains.pdf> -- [16] Casper: <https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/> -- [17] TMSP: <https://github.com/tendermint/abci> -- [18] Ethereum Sharding: <https://github.com/ethereum/EIPs/issues/53> -- [19] LibSwift: <http://www.ds.ewi.tudelft.nl/fileadmin/pds/papers/PerformanceAnalysisOfLibswift.pdf> -- [20] DLS: <http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf> -- [21] Thin Client Security: <https://en.bitcoin.it/wiki/Thin_Client_Security> -- [22] Ethereum 2.0 Mauve Paper: <https://cdn.hackaday.io/files/10879465447136/Mauve%20Paper%20Vitalik.pdf> - -#### Links não classificados - -- <https://www.docdroid.net/ec7xGzs/314477721-ethereum-platform-review-opportunities-and-challenges-for-private-and-consortium-blockchains.pdf> diff --git a/docs/resources/whitepaper-zh-CN.md b/docs/resources/whitepaper-zh-CN.md deleted file mode 100644 index 126deabd4860..000000000000 --- a/docs/resources/whitepaper-zh-CN.md +++ /dev/null @@ -1,1013 +0,0 @@ -# Cosmos -**A Network of Distributed Ledgers** - -**分布式账本网络** - -Jae Kwon jae@tendermint.com <br/> -Ethan Buchman ethan@tendermint.com - -讨论[请加入Telegram](https://t.me/cosmosproject)! - -_注意:如果你能在github上阅读,我们仍然定时更新这个文档,请定期检查更新!_ - -## Table of Contents ########################################################### - * [介绍](#介绍) - * [Tendermint](#tendermint) - * [验证人](#验证人) - * [共识](#共识) - * [轻客户端](#轻客户端) - * [防止攻击](#防止攻击) - * [ABCI](#abci) - * [Cosmos 概述](#Cosmos-概述 ) - * [Tendermint-拜占庭容错](#Tendermint-拜占庭容错) - * [治理](#治理) - * [枢纽与分区](#枢纽与分区) - * [枢纽](#枢纽) - * [分区](#分区) - * [跨链通信 IBC](#跨链通信-IBC) - * [用例](#用例) - * [分布式交易所](#分布式交易所) - * [作为其他加密货币的纽带](#作为其他加密货币的纽带) - * [以太坊的扩展](#以太坊的扩展) - * [多用一体化](#多用一体化) - * [缓解网络分区问题](#缓解网络分区问题) - * [联邦式名称解析系统](#联邦式名称解析系统) - * [发行与激励](#发行与激励) - * [Atom 代币](#Atom-代币) - * [众筹](#众筹) - * [验证人的数量限制](#验证人的数量限制) - * [成为创世日后的验证人](#成为创世日后的验证人) - * [对验证人的惩罚](#对验证人的惩罚) - * [交易费用](#交易费用) - * [激励黑客](#激励黑客) - * [治理规范](#治理规范) - * [参数变更提案](#参数变更提案) - * [文本提案](#文本提案) - * [路线图](#路线图) - * [相关工作 ](#相关工作 ) - * [共识系统](#共识系统) - * [经典拜占庭容错](#经典拜占庭容错) - * [BitShare委托权益](#BitShare委托权益) - * [Stellar](#stellar) - * [BitcoinNG](#bitcoinng) - * [Casper](#casper) - * [水平扩展](#水平扩展) - * [Interledger协议](#Interledger协议) - * [侧链](#侧链) - * [以太坊扩展性的努力](#以太坊扩展性的努力) - * [普遍扩展](#普遍扩展) - * [闪电网络](#闪电网络) - * [隔离验证人](#隔离验证人) - * [附录](#附录) - * [分叉问责制](#分叉问责制) - * [Tendermint共识](#Tendermint共识) - * [Tendermint轻客户端](#Tendermint轻客户端) - * [远程攻击的防御](#远程攻击的防御) - * [克服分叉与审查攻击](#克服分叉与审查攻击) - * [ABCI说明](#ABCI说明) - * [IBC数据包交付确认](#IBC数据包交付确认) - * [默克尔树及默克尔证明的说明](#默克尔树及默克尔证明的说明) - * [交易类型](#交易类型) - * [IBCBlockCommitTx](#ibcblockcommittx) - * [IBCPacketTx](#ibcpackettx) - * [鸣谢](#鸣谢) - * [引用](#引用) - -## 介绍 ################################################################ - - -开源的生态系统、去中心化的文件共享、以及公共的加密货币,这一系列技术的成功使人们启发和理解,去中心化的互联网协议是可以从根本上改善社会经济基础架构的。我们已经见识过个有专长的区块链应用,诸如比特币[\[1\]][1](加密货币),ZCASH [\[2\]][2] (隐私加密货币),也看到了例如以太坊 [\[3\]][3] 的大众智能合约平台,还有无数基于 EVM (以太坊虚拟机)开发的分布式应用,例如 Augur(预测市场)和 TheDAO [\[4\]][4] (投资俱乐部) - - -然而,迄今为止,这些区块链已经暴露了各种缺陷,包括总体能效低下,性能不佳或受到限制和缺乏成熟的治理机制。为了扩大比特币交易吞吐量,已经研发了许多诸如隔离见证 [\[5\]][5](Segregated-Witness)和BitcoinNG [\[6\]][6](一种新的可扩展协议)这样的解决方案,但这些垂直扩展解决方案仍然受到单一物理机容量的限制,以确保完整的可审计性。闪电网络 [\[7\]][7] 可以通过部分交易完全记录在主链账本外来扩展比特币的交易容量,这种方法十分适用于微支付和隐私保护支付通道,但是无法适用于更通用的扩展需求。 - - -理想的解决方案是允许多个并行的区块链交互操作的同时保持其安全特性。事实证明,采用工作量证明很难做到这一点,但也并非不可能。例如合并挖矿,允许在工作完成的同时,确保母链在子链上被重复使用,但交易必须通过每个节点依次进行验证,而且如果母链上的大多数哈希算力没有积极地对子链进行合并挖矿,那么就容易遭受到攻击。关于[可替代区块链网络架构的学术回顾](http://vukolic.com/iNetSec_2015.pdf) 将在附件中展示,我们也会在[相关工作](#related-work)中对其他(技术)方案和缺陷进行概括。 - - -这里我们要介绍的 Cosmos,一个全新的区块链网络架构,能够解决所有这些问题。Cosmos 是由许多被称之为“分区”的独立区块链组成的网络。分区在 Tendermint Core [\[8\]][8]的支持下运行,Tendermint Core 是一个[类似拜占庭容错](http://tendermint.com/blog/tendermint-vs-pbft/)安全共识引擎,具有高性能、一致性的特性,并且在严格的[分叉追责](#fork-accountability) 机制下能够制止恶意破坏者的行为。Tendermint Core 的拜占庭容错共识算法十分适合用于扩展权益证明(PoS)机制下的公共区块链。使用其他共识模型的区块链, 包括类似基于权益证明(PoS)的以太坊,以及比特币也能够通过使用适配分区被 Cosmos 网络连接。 - - -Cosmos 的第一个分区称之为 Cosmos 枢纽。Cosmos 枢纽是一种多资产权益证明加密货币网络,它通过简单的治理机制能够对网络进行适配和升级。此外,Cosmos 枢纽可以通过链接其他分区来实现扩展。 - - -Cosmos 网络的枢纽及各个分区可以通过区块链间通信(IBC)协议进行通信,这种协议就是针对区块链的虚拟用户数据报协议(UDP)或者传输控制协议(TCP)。代币可以安全、快速地从一个分区转到其他分区,而无需在两个分区之间拥具有汇兑流动性。相反,所有跨分区的代币转移都会通过 Cosmos 枢纽,以此来追踪记录每个分区持有代币的总量。这个枢纽会将每个分区与其他故障分区隔离开。因为每个人都可以将新的分区连接到 Cosmos 枢纽,所以分区将可以向后兼容新的区块链技术。 - - -利用 Cosmos 可以实现区块链间的互操作。这是一个具有潜力的有价值的互联网络,其中的资产由不同的验证人发布和控制,并可以在不依靠需要信任的第三方的情况下实现跨链资产无缝的转移和交易。 - -## Tendermint - - -在这一部分我们将阐述Tendermint共识协议和用于建立其应用程序的接口。 更多信息,请参见[附录](#附录) - -### 验证人 - - - -在经典的拜占庭容错算法中,每个节点有相同的权重。在 Tendermint,节点有着不同数量(非负)的 _投票权_,而那些拥有相当数量投票权的节点称之为 _验证人_。验证人通过广播加密签名、投票或者对下一个区块表决同意来参与共识协议。 - -验证者的投票权是一开始就确定好了,或者根据应用程序由区块链来决定修改投票权。例如,在像Cosmos 枢纽的权益证明应用里,投票权可由绑定为押金的代币数量来决定。 - - -注意:像⅔和⅓这样的分数指的是占总投票权的分数,而不是总验证人,除非所有验证人拥有相同权重。而>⅔ 的意思是"超过⅔ ",≥⅓则是"⅓或者更多"的意思。 - -### 共识 - - -Tendermint 是部分同步运作的拜占庭容错共识协议,这种协议源自DLS共识算法 [\[20\]][20]。Tendermint以简易性、高性能以及[分叉问责制](#fork-accountability)而著称。协议要求这组验证人固定且被熟知,并且每个验证人都有其公钥验证身份。这些验证人试图同时在一个区块上达成共识,这些区块是一系列的交易记录。每个区块的共识轮流进行,每一轮都会有个领头人,或者提议人,由他们来发起区块。之后验证人分阶段对是否接受该区块,或者是否进入下一轮做出投票。每轮的提议人会从验证人顺序列表中按照其投票权比例来选择确定。 - - -更多协议的全部细节,请点击[这里](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - - -Tendermint 采用了使用大多数投票(超过三分之二)和锁定机制的最优拜占庭容错,来确保其安全性。这些能够保证: - -* 蓄意破坏者想要造成安全性问题,必须有三分之一以上的投票权,并且要提交超过两份以上的值。 -* 如果有一组验证人成功破坏了安全性,或者曾试图这么做,他们会被协议识别。协议包括对有冲突的区块进行投票和广播那些有问题的投票。 - - -除了其超强的安全性外,Tendermint还具备杰出的性能。以商用型云平台为例,Tendermint共识以分布在五大洲七个数据中心的64位节点为基准,其每秒可以处理成千上万笔交易,订单提交延迟时间为1-2秒。而值得关注的是,即使是在极其恶劣的敌对环境中,比如验证人崩溃了或者是广播恶意破坏的投票,也能维持这种每秒超过千笔交易的较高性能。详见下图。 - -![Figure of Tendermint throughput performance](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/tendermint_throughput_blocksize.png) - -### 轻客户端 - - -Tendermint 共识算法的主要好处是具有安全简易的客户端,使其成为手机和物联网用例的理想选择。比特币轻客户端必须同步运行区块头组成的链,并且找到工作量证明最多的那一条链,而Tendermint轻客戸端只需和验证组的变化保持一致,然后简单地验证最新区块中预先提交的>⅔,来确定最新情况。 - -这种简单的轻客戸端证明机制也可以实现[区块链之间的通信](#inter-blockchain-communication-ibc)。 - -### 防止攻击 - - -Tendermint 有各种各样的防御措施来防止一些明显的攻击,比如[远程无利害关系双花攻击](#preventing-long-range-attacks) 及[审查制度](#overcoming-forks-and-censorship-attacks)。 这些在[附录](#appendix)中有更详细的讨论。 - -### ABCI - - -Tendermint共识算法是在叫做 Tendermint Core 的程序中实现的。这个程序是独立于应用的“共识引擎”,可以将任何已经确定的黑盒应用转变为分布式、可复制的区块链。Tendermint Core 可以通过应用区块链接口(ABCI) [\[17\]][17]与其他区块链应用连接。而且,应用区块链接口(ABCI) 接口允许区块链应用以任何语言编程实现,而不仅仅是写这个共识引擎所使用的语言。此外,应用区块链接口(ABCI) 也让交换任何现有区块链栈的共识层成为可能。 - - -我们将其与知名加密货币比特币进行了类比。在比特币这种加密币区块链中,每个节点都维持着完整的审核过的 UTXO(未使用交易输出)数据库。如果您想要在应用区块链接口(ABCI)基础上,创建出类似比特币的系统,那么 Tendermint Core 可以做到: - -* 在节点间共享区块及交易 -* 创建规范或不可改变的交易顺序(区块链) - - -同时,ABCI应用也可以做到: - -* 维护 UTXO 数据库 -* 验证交易的加密签名 -* 防止出现不存在的余额被交易 -* 允许客户访问UTXO数据库 - - - -## Cosmos 概述 - - -Cosmos是一个独立平行的区块链网络,其中每条区块链通过 Tendermint[1](http://github.com/tendermint/tendermint)这样的经典拜占庭容错共识算法来运行。 - - -网络中第一条区块链将会是 Cosmos 枢纽。Cosmos 枢纽通过全新的区块链间通信协议来连接其他众多区块链(或将其称之为 _分区_)。Cosmos 枢纽可以追踪无数代币的种类,并且在各个连接的分区里记录各种代币总数。代币可以安全快速地从一个分区转移到另一个分区,两者之间无需体现汇兑流动性,因为所有分区之间的代币传输都会经过 Cosmos 枢纽。 - - -这一架构解决了当今区块链领域面临的许多问题,包括应用程序互操作性、可扩展性、以及可无缝升级的能力。比如,从Bitcoind、Go-Ethereum、CryptoNote、ZCash或其他区块链系统中衍生出来的分区,都能被锚定接入 Cosmos 枢纽。这些分区允许 Cosmos 实现无限扩展,从而满足全球交易的需求。此外,分区也完全适用于分布式交易所,反之交易所也支持分区运行。 - - - -Cosmos 不仅仅是单一的分布式账本,而 Cosmos 枢纽也不是封闭式庭院或宇宙的中心。我们正在为分布式账本的开放网络设计一套协议,这套协议将基于密码学、稳健经济学、共识理论、透明性及可追责制的原则,成为未来金融系统的全新基础。 - -### Tendermint-拜占庭容错 - - -Cosmos 枢纽是 Cosmos 网络中第一条公共区块链,通过 Tendermint 的拜占庭共识算法运行。Tendermint 开源项目创立于2014年,旨在解决比特币工作量证明共识算法的速度、可扩展性以及造成的环境问题。通过采用并提高已经过验证的拜占庭算法(1988年在麻省理工学院开发)[\[20\]][20],Tendermint 成为了首个在概念论证了权益证明加密货币的团队,这种机制可以解决 NXT 和 BitShares 这些第一代权益证明加密币面临的"无利害关系"的问题。 - - -如今,实际上所有比特币移动钱包都要使用可靠的服务器来进行交易验证。这是因为工作量证明机制需要在交易被认定为无法逆转前进行多次确认。而在 Coinbase 之类的服务中也已经出现双重支付攻击。 - - -和其他区块链共识系统不同,Tendermint 提供的是即时、可证明安全的移动客户端支付验证方式。因为 Tendermint 被设计为完全不分叉,所以移动钱包就可以实时接收交易确认,从而在智能手机上真正实现去信任的支付方式。这一点也大大影响了物联网应用程序。 - - -Cosmos 中的验证人角色类似比特币矿工,但是他们采用加密签名来进行投票。验证人是专门用来提交区块的安全机器。非验证人可以将权益代币(也叫做"atom"币)委托给任何验证人来赚取一定的区块费用以及atom奖励,但是如果验证人被黑客攻击或者违反协议规定,那么代币就会面临被惩罚(削减)的风险。Tendermint 拜占庭共识的可证明安全机制,以及利益相关方(验证人和委托人)的抵押品保证,为节点甚至是轻客户端提供了可证明、可量化的安全性。 - -### 治理 - -分布式公共账本应该要有一套章程与治理体系。比特币依靠比特币基金会以及挖矿来协作更新,但是这是一个反应缓慢的治理制度。以太坊在采用硬分叉成 ETH 和 ETC 来解决 The DAO 黑客,这主要是因为之前没有设定社会契约或机制来进行这类决定。 - - -Cosmos 枢纽的验证人与委托人可以对提案进行投票,从而改变预先默认设置好的系统参数(比如区块转账费用限制),协作更新,并对可读性的章程进行修订投票,从而治理 Cosmos 枢纽制度。这个章程允许权益相关者聚集到一起,来解决盗窃及漏洞等相关问题(比如The DAO事件),并得出更快更明确的解决方案。 - - - -每个分区也可以制定自己的一套章程及治理机制。比如,Cosmos 枢纽的章程可以设置为强制实现枢纽的不可改变性(不能回滚,除了 Cosmos 枢纽节点产生的漏洞),而每个分区则可设置自己的回滚政策。 - - -Cosmos 网络能够在制度不同的分区间实现互操作性,这一点给客户极高的自由度和潜力而无需许可即可实验(新技术)。 - -## 枢纽与分区 - - -这里我们将描述一个全新的去中心化与可扩展性模型。Cosmos 网络通过 Tendermint 机制来运行众多的区块链。虽然现存提案的目标是创建一个包含全球所有交易订单的"单一区块链",但是 Cosmos 允许众多区块链在并行运行的同时,保持可互操作性。 - - -在这个基础上,Cosmos枢纽负责管理称之为“分区”的众多独立区块链(有时也叫做"分片",参考自众所周知的数据库扩展技术"分片")。枢纽上的分片会源源不断地提交最新区块,这一点可以让枢纽同步每一个分区的状态。同样地,每个分区也会和枢纽的状态保持一致(不过分区之间不会同彼此的同步,除非间接通过枢纽来实现)。通过发布默克尔证明来证明消息被接受和发送,来让消息从一个分区传递到另一个分区。这种机制叫做"区块链间通信",或者简称为"IBC"机制。 - -![Figure of hub and zones acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/hub_and_zones.png) - - -任何分区都可以自行成为枢纽来建立非循环图表,但为了清楚起见,我们只描述这种只有一个枢纽和许多非枢纽的分区这样简单的配置 - - -### 枢纽 - - -Cosmos枢纽是承载多种分布式账本资产的区块链,其中代币可以由个人或分区自己持有。这些代币能够通过特殊的IBC数据包,即"代币数据包"(coin packet)从一个分区转移到另一个分区。枢纽负责保持各个分区中各类代币总量不变。IBC代币数据包交易必须由发送人、枢纽及区块接受者执行。 - - - -因为Cosmos枢纽在整个系统中扮演着中央代币账本的角色,其安全性极其重要。虽然每个分区可能都是一个Tendermint区块链——只需通过4个,(或者在无需拜占庭容错共识的情况下更少的验证人来保证安全),但是Cosmos枢纽必须通过全球去中心化验证组来保证安全,而且这个验证组要能够承受最严重的攻击,比如区域网络分裂或者由国家发起的攻击。 - -### 分区 - - -Cosmos分区是独立的区块链,能够和Cosmos枢纽进行IBC消息交换。从枢纽的角度上看,分区是一种多重资产、动态会员制的多重签名账户,可以通过IBC数据包用来发送和接受代币。就像加密币账户一样,分区不能转移超出其持有量的代币,不过可以从其他拥有代币的人那里接收代币。分区可能会被指定为一种或多种代币的"来源",从而赋予其增加代币供应量的权力。 - - -Cosmos 枢纽的 Atom 或可作为分区验证人连接到枢纽的筹码。虽然在Tendermint分叉责任制下,分区出现双重支付攻击会导致atom数量减少,但是如果分区中有超过⅔的选票都出现拜占庭问题的话,那这个分区就可以提交无效状态。Cosmos 枢纽不会验证或执行提交到其他分区的交易,因此将代币发送到可靠的分区间就是用户的责任了。未来 Cosmos 枢纽的管理系统可能会通过改善提案,来解决分区故障问题。比如,在检测到袭击时,可以将有些分区(或全部分区)发起的代币转账将被暂停,实现紧急断路(即暂时中止代币转账)。 - -## 跨链通信-IBC - -现在我们来介绍下枢纽与分区之间通信的方法。假如现在有三个区块链,分别是"分区1"、“分区2"以及"枢纽”,我们想要"分区1"生成一个数据包,通过"枢纽"发送给"分区2"。为了让数据包从一个区块链转移到另一个区块链,需要在接收方区块链上发布一个证明,来明确发送方已经发起了一个数据包到指定目的地。接收方要验证的这个证明,必须和发送方区块头保持一致。这种机制就类似与侧链采用的机制,它需要两个相互作用的链,通过双向传送存在证明数据元(交易),来"知晓"另一方的情况。 - -IBC协议可以自然定义为两种交易的使用:一种是IBCBlockCommitTx 交易,这种交易可以让区块链向任何观察员证明其最新区块哈希值;另一种是IBCPacketTx 交易,这种交易则可以证明某个数据包确实由发送者的应用程序,通过默克尔证明机制(Merkle-proof)传送到了最新区块的哈希值上。 - -通过将IBC机制分离成两个单独的交易,即IBCBlockCommitTx 交易与 IBCPacketTx 交易,我们可以让接收方链的本地费用市场机制,来决定承认哪个数据包,与此同时还能确保发送方的完全自由,让其自行决定能够传出的数据包数量。 - -![Figure of Zone1, Zone2, and Hub IBC without acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_without_ack.png) - - - - -在上述案例中,为了更新"枢纽"上"分区1"的区块哈希(或者说"分区2"上"枢纽"的区块哈希),必须将IBCBlockCommitTx交易的"分区1"区块哈希值发布到"枢纽"上(或者将该交易的"枢纽"区块哈希值发布到"分区2"中)。 - -_关于两种IBC交易类型,详细请参见 [IBCBlockCommitTx](#ibcblockcommittx) 和 [IBCPacketTx](#ibcpacketcommit) - -## 用例 - -### 分布式交易所 - -比特币借助大量复制来增加分布式账本的安全性。用类似的方式,我们可以在区块链上运行交易所,来降低其受内部及外部攻击的可能性。我们称之为去中心化交易所。 - -现今,加密货币社区认为的去中心化交易所基于"跨链原子事务"交易( AXC 交易)。通过AXC交易,两条不同链上的两个用户可以发起两笔转账交易,交易在两个账本上要么一起提交执行,或者两个账本都不执行(即交易的原子性)。比如,两位用户可以通过AXC交易来实现比特币和以太币之间的交易(或是在不同账本上的任意两种代币),即使比特币和以太坊的区块链之间并没有彼此连接。AXC 交易模式下的交易所用户双方不需要彼此信任,也不用依赖交易匹配服务。其弊端是,交易双方必须同时在线才能进行交易。 - -另一种去中心化交易所是进行大量复制的具有独立区块链的分布式交易所。该种交易所的用户可以提交限价订单并关闭他们的计算机,交易可以在用户离线状态下执行。区块链将会代表交易者去完成匹配和交易。 - -一个中心化的交易所可以构建一个有大交易量的限价交易的买卖盘账目,以此来吸引更多的交易者。在交易所领域,流动性会引发更多流动性,因此在交易所业务中,其具有的网络效应也愈发明显(或者说至少产生了"赢家通吃"效应)。目前加密货币交易所 Poloniex 以每24小时2,000万美元的交易量排名第一, Bitfinex 则每24小时500万美元的交易额位列第二。在这种强大的网络效应之下,基于AXC的去中心化交易所的成交量是不太可能超过中心化交易所。去中心化交易所要想和中心化交易所一争高下,就需要支持以限价订单构成的具有深度的交易买卖盘账目的运行。而只有基于区块链的去中心化交易所可以实现这一点。 - -Tendermint提供的快速交易执行是另一大优势。Cosmos的内部网络可以在不牺牲一致性的前提下优先快速的确定最终性,来实现交易的快速完成 —— 同时针对交易订单交易,以及IBC(跨区块链通信)代币与其他网络的交易。 - -综上,根据现有加密货币交易所的情况,Cosmos的一项重大应用就是去中心化交易所(称为 Cosmos DEX)。其交易吞吐能量和委托延时可以与那些中心化交易所媲美。交易者可以在各方离线的状态下提交限价订单。并且,基于Tendermint,Cosmos枢纽以及IBC的情况下,交易者可以快速地完成在交易所及其他网络的资金进出。 - -### 作为其他加密货币的纽带 - -特权分区可以作为和其他加密货币挂钩的代币来源。这种挂钩类似Cosmos枢纽与分区之间的关系,两者都必须及时更新彼此最新的区块链,从而验证代币已经从一方转移到另一方。Cosmos网络上挂钩的”桥接分区“要和中心以及其他加密币保持同步。这种间接通过”桥接分区“可以保持枢纽逻辑的简洁。并且不必要了解其他的链上共识战略,如比特币工作量证明挖矿机制。 - -#### 向Cosmos枢纽发送代币 - -每个挂钩桥接分区的验证人都会在基于Tendermint公式的区块链之上,运行带有特殊的ABCI桥接应用程序,但同时也会运行一个原有区块链的“全节点”。 - -在原有区块链挖出新区块时,桥接分区验证人员将通过签署和分享起始点区块链的提示,各自局部视角可以达成一致。当一个桥接分区收到原有区块链的支付时(如在以太坊或比特币等PoW机制的链上有足够数目的确认),则在该桥接分区上创建具有该对应账户的余额。 - -就以太坊而言,桥接分区可以和Cosmos枢纽共享相同的验证人。以太坊方面(原本区块链),一个桥接合约将允许以太拥有者通过将以太币发送到以太坊的桥接分区的桥接合约上。一旦挂桥接合约接收到以太币,以太币就不能被撤回,除非从桥接分区接收到对应的IBC数据包。桥接合约跟随桥接分区的验证组,它可能与Cosmos枢纽的验证人组相同。 - -就比特币而言,概念是相似,除了代替一个桥接合约,每个UTXO将由一个门限多重签名P2SH数据库限制。由于P2SH系统的限制,签名者不能与Cosmos枢纽的验证人组相同。 - -#### 从Cosmos枢纽提出代币 - -桥接分区上的以太币(“桥接以太币”)可以在枢纽间转进,转出,完成传送到特定以太坊提取地址后,转出的“桥接以太币”被彻底删除。一个IBC消息可以证明桥接分区上的交易,这个消息将被公布到以太坊桥接合约中,以便以太币被取出。 - -就比特币而言,严谨的交易脚本系统让IBC币的镜像转换机制很难实现。每个UTXO都有自己的特定的脚本,所以当比特币履约签名者发生变化时,每个UTXO都必须迁移到新的UTXO。一个解决方案是根据需要,压缩和解压缩UTXO-set,以保持UTXO的总数量下降。 - -#### 挂钩区完全责任制 - -这类挂钩合约存在风险的风险是,可能会出现恶意的验证人组。如果拜占庭投票权超过⅓,就会造成分叉,即从以太坊桥接合约中提取以太币的同时,还能保持桥接分区中的挂钩以太币不变。甚至,如果拜占庭投票权超过⅔,可能会有人直接通过脱离原始桥接分区的桥接逻辑,对发送以太币发到桥接合约中的帐户下手,盗取以太币。 - -如果将这个桥接方法完全设计成责任制,就有可能解决这一问题。比如,枢纽及起始点的全部IBC包裹可能需要先通过桥接分区的认可,即让枢纽或起始点中的桥接合约对桥接分区的所有状态转换进行有效验证。枢纽及起始点要允许桥接分区的验证人提供抵押物,而侨界合约的代币转出需要延时(且抵押品解绑时间也要足够长),从而让单独的审计人有时间发起任何的质询。我们会把这一系统的设计说明以及执行方式开放,作为未来Cosmos改善的提议,以待Cosmos枢纽的管理系统审批通过。 - -### 以太坊的扩展 - - -众所周知,扩展问题是一直困扰着以太坊的问题。目前以太坊节点会处理节点上每笔交易,并且存储所有的状态[参考](https://docs.google.com/presentation/d/1CjD0W4l4-CwHKUvfF5Vlps76fKLEC6pIwu1a_kC_YRQ/mobilepresent?slide=id.gd284b9333_0_28).。 - -Tendermint提交区块的速度比以太坊工作量证明要快,所以由Tendermint共识推动且使用桥接以太币运行的以太坊虚拟机分区能够强化太坊区块链的性能。此外,虽然Cosmos枢纽及IBC包裹机制不能实现每秒合约逻辑的执行,但是它可以用来协调不同分区中以太坊合约之间的代币流通,通过分片方式为以代币为中心的以太坊扩展奠定基础。 - -### 多用一体化 - -Cosmos分区可以运行任意的应用逻辑,应用在分区创建时设定好,可通过管理者可以不断更新。这种灵活度使得Cosmos分区可以作为其他加密币的挂钩载体,比如以太坊或比特币,并且它还能和这些区块链的衍生品挂钩,利用同样的代码库,而在验证程序及初始分配有所区分。这样就允许多种现有加密币框架得以运行,如以太坊、Zerocash、比特币、CryptoNote等等,将其同Tendermint Core结合,成为通用网络中性能更优的共识引擎,为平台之间提供更多的交互机会。此外,作为多资产区块链,每笔交易都有可能包含多个输入输出项,其中每个输入项都可以是任意代币,使Cosmos直接成为去中心化交易所,当然这里假设交易订单通过其他平台进行匹配。替代方案是,让分区作为分布式容错交易所(包含买卖盘账目),这算是对中心化加密币交易所之上的严格改进——现行交易所在过去时常发生被攻击的事件。 - -分区也可以作为区块链版的企业及政府系统,其原本由一个或多个组织运行的特定服务,现在作为ABCI应用在某个分区上运行,从而在不放弃对底层服务控制的前提下,维持公共Cosmos网络的安全性及交互性。所以,Cosmos或可为那些既想使用区块链技术,又不愿彻底放弃控制权给分布式第三方的人,提供绝佳的运行环境。 - -### 缓解网络分区问题 - -有人认为像Tendermint这种支持一致性的共识算法有一个重大问题,就是网络分区会导致没有任何一个分区会拥有超过⅔的投票权(比如超过⅓投票权在线下),这会中断共识。而Cosmos架构可以缓解这个问题,它可以使用全球中心,同时,各分区实行地区自治,然后让每个分区的投票权按照正常的地域位置进行分配。如,一般范例就有可能是针对个别城市或地区的,让他们各自运行自己分区的同时,还能共享共同的枢纽(比如Cosmos枢纽),并且在临时的网络分区导致的中断期间,也可以继续维持地区自治活动。注意,这样一来在设计稳健的联邦式容错系统过程中,就可以去考虑真实的地理、政治及网络拓扑的特征了。 - -### 联邦式名称解析系统 - -NameCoin是首批试图通过比特币技术解决名称解析问题的区块链之一。不过,这个方案存在一些不足。 - -例如,我们可以通过Namecoin来验证@satoshi(聪)这个号是在过去某个时间点用特定公钥进行注册的。但是,该公钥是否更新过我们就不得而知了,除非将该名称最后一次更新之前的所有全部下载。这一点是比特币UTXO交易模式中默克尔化模型的局限性导致的,这类模型中只有交易(而非可变的应用状态)会以默克尔化加入到区块哈希中。它让我们得在之后用更新证明名称的存在,而非不存在。因此,我们必须依靠全节点才能明确这个名称的最近的值,或者花费大量资源下载整个区块链。 - -即使在NameCoin上运用默克尔化的搜索树,其工作量证明的独立性还是会导致轻客戸端的验证出现问题。轻客戸端必须下载区块链中所有区块头的完整备份(或者至少是自其最后的名称更新的所有区块头)。这意味着带宽需要随着时间做线性的扩展。 [21]此外,在工作量证明制度使区块链上的名称更改需要等额外的工作量证明验证确认才能进行,它在比特币上可能要花费一个小时。 - - -有了Tendermint,我们只需用到由法定数量验证人签署(通过投票权)的区块哈希,以及与名称相关的当前值的默克尔证明。这点让简易、快速、安全的轻客戸端名称值验证成为可能。 - -在Cosmos中,我们可以利用这个概念并延伸。每一个在Cosmos上的名称注册都能有一个相关的最高级别域名(TLD),比如".com"或者".org"等,而且每个名称注册分区都有自己的管理和登记规则。 - -## 发行与激励 - -### Atom 代币 - -Cosmos 枢纽是多资产分布式账本,它有自己的代币,是 Atom 。Atom 是 Cosmos 枢纽唯一的权益代币。Atom是持有人投票、验证或委托给其他验证人的许可证明,就像以太坊上的以太币一样,Atom也可以用来支付交易费以减少电子垃圾。额外的通胀 Atom 和区块交易费用就作为激励分给验证人及委托验证人。 - -`BurnAtomTx`交易可以用来恢复储蓄池中任意比例的代币。 - -#### 众筹 - -创世块上的 Atom 代币及验证人的初次分发是 Cosmos 众售参与者持有75%,预售参与者持有5%,Cosmos网络基金会持有10%,ALL IN BITS, 集团持有10%。从创世块开始,Atom 总量的1/3将作为奖励发放给每年担保持有的验证人以及委托人。 - -更多细节见 [Cosmos Plan](https://github.com/cosmos/cosmos/blob/master/PLAN.md) - -### 验证人的数量限制 - -与比特币或其他工作量证明区块链不同的是, 由于通信的复杂性增加, Tendermint 区块链会随着验证人的增加而变慢。幸运的是, 我们可以支持足够多的验证人来实现可靠的全球化分布式区块链, 并具有非常快的交易确认时间。 而且随着带宽、存储和并行计算容量的增加, 我们将来能够支持更多的验证人。 - -在创世日, 验证人的最大数量将设置为 100, 这个数字将以13% 的速度增长10年, 最终达到300位。 - -``` -Year 0: 100 -Year 1: 113 -Year 2: 127 -Year 3: 144 -Year 4: 163 -Year 5: 184 -Year 6: 208 -Year 7: 235 -Year 8: 265 -Year 9: 300 -Year 10: 300 -... -``` - -### 成为创世日后的验证人 - - -Atom 持有者可以通过签署和提交 `BondTx` 交易成为验证人。抵押的 atom 数量不能为零。任何人任何时候都成为验证人, 除非当前验证人组的数量超过了最大值。在这种情况下, 只有当持有 atom 的数量大于现有验证人中持有有效 atom 数量的最少者, 该交易才有效, 其中有效 atom 包括受委托的 atom。当一个新的验证人以这种方式替换现有的验证人时, 现有的验证人将离线, 其所有的 atom 和受委托的 atom 进入解绑状态。 - -### 对验证人的惩罚 - - -对于任何有意或无意的偏离认可协议的验证人, 必须对其施加一定的惩罚。有些证据立即可予受理, 比如在同样高度和回合的双重签名, 或违反 "预投票锁定" (Tendermint 协商一致议定书的规则)。这样的证据将导致验证人失去其良好的声誉, 其绑定的 atom 以及在储备池中的比例份额 – 统称为 “权益” – 将被大幅削减。 - -有时, 由于区域网络中断、电源故障或其他原因, 验证人将不可用。如果在过去任意时间点的 `ValidatorTimeoutWindow` 块中, 验证人的提交投票不包括在区块链中超过 `ValidatorTimeoutMaxAbsent` 次, 该验证人将离线, 并减少 `ValidatorTimeoutPenalty` (默认 1%) 的权益。 - - -一些 "恶意" 行为在区块链上并没有产生明显的证据。在这些情况下, 如果存在多数的协商一致, 则验证人可以在带外协调,强制将这些恶意验证人超时。 - - -如果 Cosmos 枢纽 因为超过⅓的投票权离线而出现了中止情况,或者说超过⅓的投票权审查到进入区块链的恶意行为,这时候枢纽就必须借助硬分叉重组协议来恢复。(详见“分叉与审查攻击”) - -### 交易费用 - - -Cosmos 枢纽验证人可以接受任何种类的代币或组合作为处理交易的费用。每个验证人可自行设置兑换率, 并选择其想要的交易, 只要不超过 `BlockGasLimit`, 每隔 `ValidatorPayoutPeriod` (默认为1小时) 时间会根据权益相关人绑定的 Atom 比例进行分配。 - - -在所收取的交易费用中, `ReserveTax` (默认 2%) 将存入储备池来增加储备量, 增加 Cosmos 枢纽的安全性和价值。这些资金也可以按照治理系统的决策进行分配。 - - -将投票权委托给其他验证人的 Atom 持有人会支付一定佣金给委托方,而这笔费用可以由每个验证人进行设置。 - -### 激励黑客 - -Cosmos 枢纽的安全取决于底层验证人的安全性和委托人的委托选择。为了鼓励发现和早期报告发现的漏洞, Cosmos 枢纽鼓励黑客通过 `ReportHackTx` 交易发布成功的漏洞, 说, "这个验证人被入侵了,请把赏金发送到这个地址"。这种情况下, 验证人和委托人将挂起闲置, 每个人 `HackPunishmentRatio` (默认 5%) 的 atom 将被削减, `HackRewardRatio` (默认 5%) 的 atom 将发送到黑客的赏金地址作为奖励。验证人必须使用其备份密钥来恢复剩余的 atom。 - -为了防止这一特性被滥用于转移未授权的 atom, 在 `ReportHackTx` 前后,Atom的比例(授权的与未授权的) 将保持不变, 而黑客的赏金将包括一些未授权的 atom (如果有的话)。 - -### 治理规范 - -Cosmos 枢纽是由一个分布式组织管理的, 需要一个明确的治理机制, 以协调对区块链的各种变化, 如系统的参数变量, 以及软件升级和宪法修订. - -所有验证人负责对所有提案进行表决。如果未能及时对提案进行表决, 将导致验证人被自动停用一段时间。 这段时间被称为 `AbsenteeismPenaltyPeriod` (默认1周)。 - - -委托人自动继承其委托的验证人的投票权。这一投票可以被手动覆盖掉。而未绑定的 Atom 是没有投票权的。 - - -每个提案都需要 `MinimumProposalDeposit` 代币的保证金, 这可能是一个或多个代币 (包括atom) 的组合。对于每项提案, 投票者可以投票表决取走保证金。如果超过半数的投票者选择取走保证金 (例如, 因为提案是垃圾信息), 那么保证金就会存入储备池, 除了被燃烧的 atoms。 - -对于每项提案, 投票人可以选择下列方案: - -* 同意 -* 强烈同意 -* 反对 -* 强烈反对 -* 弃权 - -决定采纳(或不采纳)提案需要严格的多数投“同意”或“强烈同意”(或者“反对”及“强烈反对”),但是超过1/3的人投“强烈反对”或“强烈支持”的话就可以否决大多数人的决定。如果大多数人票被否决,那么他们每个人都会失去 `VetoPenaltyFeeBlocks` (默认是一天的区块值 ,税费除外) 作为惩罚,而否决大多数决定的那一方还将额外失去 `VetoPenaltyAtoms` 默认为0.1%)的 Atom 作为惩罚。 - -### 参数变更提案 - - -这里定义的任何参数都可在 `ParameterChangeProposal` 通过后改变。 - -### 赏金提案 - - -通过 `BountyProposal` 后, Atom 可以增发和预留储备池资金作为赏金。 - -### 文本提案 - - -所有其他提案,比如用来更新协议的提案,都会通过通用的 TextProposal 来协调。 - - -## 路线图 - - -详见[计划](https://github.com/cosmos/cosmos/blob/master/PLAN.md). - -## 相关工作 - -过去几年涌现了很多区块链共识及扩展性方面的创新。在这一部分中将挑选一些重要的创新进行简单分析。 - -### 共识系统 - -#### 经典拜占庭容错 - -二十世纪八十年代早期就开始研究存在恶意参与者的共识机制,当时Leslie Lamport创造了”拜占庭容错”这个词,用来指那些图谋不轨参与者做出的恶意的行为,与”死机故障”不同,后者只是处理过程崩溃而已。早期针对同步网络也探索出了一些解决方案,网络信息滞后有一个上限,但实际使用是在高度受控的环境下进行,比如精密飞行仪器以及使用原子钟同步的数据中心。直到九十年代后期,实用拜占庭容错( Practical Byzantine Fault Tolerance ,PBFT)[\[11\]][11]才作为有效的、部分同步的共识算法被逐步推广。它可以容忍⅓参与者有恶意行为。PBFT成为标准算法,催生了各种版本,包括最近由IBM提出并使用于Hyperledger超级账本中的算法。 - -和PBFT相比,Tendermint共识的主要好处在于其改善且简化了的底层结构,其中有些是遵循了区块链典范的结果。Tendermint中,区块必须按顺序提交,这就消除复杂性,节省PBFT中状态变化相关的通信开支。在Cosmos和众多加密币中,如果区块N本身没有提交,那么就不能让它之后的区块N+i(i>=1)提交。如果是通信带宽限制导致了区块N未提交到Cosmos Zone上,那么将通信带宽用于分享选票给区块N+i是一种浪费。如果由于网络分区或者节点掉线导致的区块N未提交,那么N+i就无论如何也不能提交。 - -此外,将交易打包成块可以用默克尔哈希纪录应用程序的状态,而不是用PBFT检查机制进行定时摘要。这可以让轻客戸端更快的提交交易证明,以及更快的跨链通信。 - -Tendermint Core中也优化了很多PBFT特性以外的功能。比如,验证人提交的区块被分割多个部分,对其默克尔化后,然后在节点间广播。这种方式可以提高其广播性能(具体请查看LibSwift [19])。而且,Tendermint Core不会对点对点连接做任何假设,只要点对点间的网络不断开,那么它就能正常运行。 - -#### BitShare委托权益 - -BitShares [\[12\]][12]不是第一个采用权益证明机制(proof-of-stake,PoS)的区块链,但是其对PoS在区块链上的研究与推进做出了巨大的贡献,尤其是在DPoS,即受委托权益证明方面。在BitShares中,相关方选择”见证者”负责提交交易顺序并提交;相关方选择”委托人”负责协调软件更新与参数变化。尽管BitShare在理想环境下能达到很高的性能:100k tx/s,1秒的滞后。每一块只有一个单独的签名,得到交易的最终性的时间比区块时间略长。一个标准的协议仍在开发中。利益相关者可以每天去除或者替换有恶意行为的验证人,但是不同于Tendermint PoS的保证金机制,BitShares没有要求验证人或者代理人的提交押金,如果发生双花攻击的话,押金不会被削减。 - -#### Stellar - -Stellar [\[13\]][13]是以Ripple推行的解决方案为基础,它优化了联邦拜占庭协议模型,其中参与共识过程的并不构成一个固定的全局过程。 相反,每个进程节点组织一个或多个“仲裁片”,每个“仲裁片”构成一组可信进程。 Stellar中的“法定人数”被定义为一组包含至少个个节点的一个仲裁片。从而可达成一致。 - -恒星机制的安全性依赖于任何两个仲裁的交集都是非空的假设,同时,节点的可用性要求至少一个“仲裁片”完全由诚实节点组成。这就需要在“法定人数”的大小上作出妥协:人数过少难以获得共识,人数过多则难以信任所有人。可能难以平衡而不对信任做出重大假设。 除此之外,节点必须维护一定数量的仲裁片以获得足够的容错能力(或者任何“完整节点”,大部分结果的依赖),并且提供一种层级化的配置策略,类似于边界网关协议(Border Gateway Protocol,BGP)。BGP被互联网服务供应商(Internet Service Provider,ISP)用来建立全球路由表,也被浏览器用来管理传输层安全协议(Transport Layer Security,TLS)证书。他们都因为不安全而臭名昭着。 - - -对于Stellar论文中基于Tendermint的PoS批评可以通过本文描述的代币策略来缓解。本文提出了名为 _atom_ 的新的代币,它代表未来交易过程中产生的费用和奖励。 基于Tendermint PoS的优势在于其原理相对简单,同时仍可充分保证和证明安全性。 - -#### BitcoinNG - -BitcoinNG是对比特币的改进,允许垂直扩展,比如增加块的大小而避免带来负面的经济后果,例如对矿工造成的影响严重不成比例。 这种改进是通过将leader选举与交易广播分开来实现的:leader首先通过“微块micro-blocks”的PoW选举,然后leader能够广播交易直至下一个新的“微块”。 这减少了赢得PoW比赛所需的带宽要求,使矿主竞争更公平,并通过允许最后一名矿工提交微块以加快交易提交频率。 - -#### Casper - -Casper [\[16\]][16]是以太坊提出的PoS共识算法。 它的主要操作模式是“预测押注”的一致。 通过让验证者基于他们目前看到的其他投注来迭代地下注他们认为哪个块将提交入区块链。最终性可以立即实现。 - -[链接](https://blog.ethereum.org/2015/12/28/understanding-serenity-part-2-casper/). 这是Casper团队研究的一个热点领域。 挑战在于构建一个可以证明是一个演化稳定策略的投注机制。 与Tendermint相比,Casper的主要优势可能在于提供“可用性超越一致性” — 达成共识不需要超过50%的投票权 — 可能是以提交速度或实现复杂性为代价的。 - -### 水平扩展 - -#### Interledger协议 - -Interledger协议(The Interledger Protocol,ILP)[\[14\]][14]不是一种严格的扩展方案。 它通过一个松散耦合的双边关系网络,提供一种指定的跨不同账本系统交互操作。像闪电网络一样,ILP的目的是实现支付,但是它特别关注跨账本类型的支付,并扩展原子事务的处理机制,使得事务的处理不仅支持哈希锁,而且还包括法定人数的公证人(称为原子运输协议)。 后者在账本间交易中实施原子性的机制与Tendermint的轻客户SPV机制类似,因此比较ILP和Cosmos / IBC之间的区别是有必要的,具体见下文。 - -1.ILP不支持连接器公证员的变更,也不允许公证员之间有灵活的权重。 另一方面,IBC是专门为区块链设计的,验证人可以拥有不同的权重,并且随着区块链的发展,成员可以随时更改。 - -2.与闪电网络一样,ILP中的接收人必须在线才能向发起人发送确认。 在IBC代币传输中,接收者所在区块链的验证人集合负责提供确认,而不是接收用户本人。 - -3.最大的不同在于ILP连接器不需要负责对支付状态保持权威性,然而在Cosmos中,hub的验证人负责IBC代币传输状态和每个zone内持有代币数量的权威性。允许从zone之间的安全地不对称地交换代币是本质的创新。在cosmos中的ILP连接器可以看作是一个持久和最安全的区块链分类账:cosmos hub。 - -4.ILP内的跨账本支付需要一个交易所的指令集的支持。因为不存在从一个分类账到另一个分类账不对称的代币转移,只能做到市场等价物的转移。 - -#### 侧链 - -Sidechains [\[15\]][15]是一种通过使用与比特币区块链“双向挂钩”替代区块链来扩展比特币网络性能的机制。(双向挂钩相当于桥接,在cosmos中被称为“桥接”与市场挂钩区分)。侧链使得比特币可以方便的在比特币区块链和侧链间移动,并允许在侧链上实验新功能。在Cosmos Hub中,侧链和比特币是彼此的轻客户端,在比特币区块链和侧链间移动时使用SPV证明。当然,由于比特币使用PoW,以比特币为中心的侧链遭受许多由于PoW作为共识机制的引起的问题和风险。而且,这是一个比特币利益最大化的解决方案,并不像Cosmos那样本地支持各种代币和zone间网络拓扑结构。但是,双向挂钩的核心机制原则上与Cosmos所采用的机制相同。 - -#### 以太坊扩展性的努力 - - -以太坊目前正在研究许多不同的战略,将以太坊区块链的状态分区化,以解决可扩展性的需求。 这些努力的目标是在共享状态空间之上,维持当前以太坊虚拟机提供抽象层。 目前,多项研究工作正在进行。[\[18\]][18] [\[22\]][22] - -##### Cosmos vs Ethereum 2.0 Mauve - - -Cosmos 和 Ethereum 2.0 Mauve [\[22\]][[22] 有不同的设计理念。 - -* Cosmos是针对代币儿 Mauve 是关于扩大计算能力。 -* Cosmos不仅限于 EVM, 所以即使不同的VM也可以交互。 -* Cosmos 让zone的创建者决定验证人。 -* 任何人都可以在Cosmos中建立新的zone(除非管理者另做决定)。 -* hub与zone的失效隔离,所以全局的代币不变量可以保持。 - -### 普遍扩展 - -#### 闪电网络 - - -闪电网络被设计成一种代币传输网络,在比特币区块链(及其他公有区块链)上一层运行,通过把大部分交易从共识分类账之外转移到所谓的“ 付款渠道“。 这通过链上加密货币脚本来实现,这些脚本使双方能够进入双方持有的状态化合同,通过共享数字签名来更新状态,并且在合同结束后最终通过在区块链上发布证据,这种机制首先受到跨链原子互换交易的欢迎。 通过与多方开通支付渠道,闪电网络的参与者可以成为集中点,为其他人的支付提供路由,从而导致支付渠道网络的完全联通,其代价是绑定在支付渠道上的资金。 - -虽然闪电网络也可以轻松地跨越多个独立的区块链,并借助交易市场实现价值转移,但它不能实现从一个区块链到另一个区块链的非对称代币交易。 这里描述的Cosmos网络的主要优点是实现直接的代币交换。 也就是说,我们希望支付渠道和闪电网络将会与我们的代币传输机制一起被广泛采用,从而节省成本和保护隐私。 - -#### 隔离验证人 - - -隔离见证是一个比特币改进建议BIP,[链接](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) 旨在将每块交易吞吐量提高2倍或3倍,同时使新节点能更快同步区块。 这个解决方案的亮点在于它如何在比特币当前协议的局限下,允许软分叉升级(例如,具有旧版本软件的客户端将在升级后仍可继续运行)。 Tendermint作为一个新的协议没有设计的限制,所以它具有不同的扩展优先级。 TendermintBFT的循环算法,主要基于加密签名而不是采矿,这种算法允许通过多个并行区块链进行水平扩展,而更常规、更频繁的区块提交也允许垂直扩展。 - - - -## 附录 - -### 分叉问责制 - -经过精心设计的共识协议应该能够在超出容错能力或者共识出错的情况下为系统提供一定的保障。这在能够通过拜占庭行为获取实质经济回报的金融系统中显得尤为必要。_分叉问责制_ 就属于这种非常重要的保障机制,这种制度会使一个导致共识出错的进程(例如使协议客户端开始接受不同值——即分叉)被识别出来,并且根据协议规则对其进行惩罚,甚至将其移送至司法系统处置。但当司法系统不可靠或者诉讼费极其昂贵时,为了让验证人们都参与到这个机制当中,该制度会强制要求他们建立安全保证金,一旦检测到恶意行为,那么这些保证金将会被罚没或者削减[\[10\]][10]. - - - -注意这与比特币有所不同,由于网络非同步与局部哈希碰撞的概率特性,比特币的分叉是定期出现的。因为在很多情况下,恶意分叉与非同步引起的分叉是无法分辨的,除非让矿工为挖到的孤立区块支付隐性的机会成本,否则比特币就很难准确地执行分叉问责制。 - -### Tendermint共识 - - -我们把投票阶段分为 _预投票_ 和 _预提交_ 两个阶段。一个投票可以是用于特定区块,也可以用于 _Nil_。我们把同一轮超过⅔的单个区块的预投票总和称为 _Polka_ ,把同一轮超过⅔的单个区块的预提交总和称为 _Commit_。如果在同一轮中对Nil的预提交超过⅔,他们就进入到下一轮中。 - - -注意到协议中的严格的确定性会引发一个弱同步假设,因为错误的发起者必须被检测到并将其略过。验证人们在为Nil预投票之前会等待一段时间,称之为超时提议,这个超时提议的hi等待时间也会随着每一轮的进行而递增。每一轮的进行都是完全不同步的,在这个过程中,只有当验证人收听到超过⅔的网络投票才能进入到下一轮中。实际上,它需要极其强大的阻碍才能阻挠这个弱同步假设(导致无达成共识,无法提交区块),而且通过每个验证人超时提议(TimeoutPropose)的随机值还可更加提高这么做的难度。 - -另一个附加的约束条件,或者叫锁定条例,它能确保网络最终在每个高度只提交一个区块。任何试图在给定高度提交超过一个区块的恶意行为都会被识别出来。首先,一个区块的预提交必须被认为是正当的,并且以Polka的形式提交。如果验证人已经准备在R_1轮中预提交一个区块,我们称他们锁定了这个区块,并且然后用于验证R_2轮新预提交动作的Polka必须进入R_polka轮,其中 R_1 < R_polka <= R_2。其次,验证人们必须为他们锁定的区块提议并且(或者)预投票。这两个条件共同作用,确保了验证人在对其正当性没有充分论证的情况下不能进行预提交操作,并且保证已经完成预提交的验证人不能再为其他东西的预提交贡献证明投票。这样不但可以保证共识算法的安全性,还能保证它的活跃度。 - - -关于这一协议的全部细节参考[这里](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - -### Tendermint轻客户端 - -因为生成侧链(一个分叉)意味着至少⅓的担保权益被罚没,Tendermint权益证明(Tendermint-PoS)取消了同步所有区块头的要求。当然,罚没保证金也是需要有人共享分叉证据的,所以轻客戸端就要存储任何它见证的区块哈希提交。另外,轻客戸端可以定期地与验证人组的改变保持同步,以避免出现远程攻击(但是其他解决方案也具有可能性)。 - - -与以太坊类似,Tendermint能够让应用程序在每个区块中嵌入一个全局默克尔根的哈希值,可以简单方便的验证的状态查询,比如查询账户余额、在智能合约中的值,或者未使用交易输出(UTXO)的存在,具体由应用程序的特性决定。 - -### 远程攻击的防御 - - -假设有一个足够有弹性的广播网络采集与一组静态验证人组存在,那么任何区块链分叉都可以被检测到,而且发起攻击的验证人提交的保证金会被罚没。这个由Vitalik Buterin在2014年首次提出的新方法,解决了其他权益证明加密货币的"没有任何相关权益"问题(详见 [相关工作部分](#related-work))。但由于验证人组必须是能够变化的,在较长的时间段内最初的一些验证人会解除j押金绑定,这就使他们可以自由地从创世区块中创建新链,并且因为他们不再有被锁定的保证金,他们将不需要为这个行为支付任何费用。这类攻击被称为远程攻击(LRA),与短程攻击相比,后者对处在押金绑定中的验证人发起的分叉是可以对其进行惩罚的(假设有类似Tendermint共识这样的分叉问责制拜占庭容错算法)。所以远程攻击经常被认为是对权益证明机制的一种危险打击。 - - -幸运的是,远程攻击(LRA)可以用以下的途径来缓解。第一,对于解除绑定的验证人而言(取回抵押保证金并且不再从参与共识中获取费用),保证金在一定时间内不能转移,也可以称其为"解绑周期",这个周期可能长达数周或数月。第二,对于轻客户端的安全性而言,其首次连接到网络时必须根据可信源验证最新的一个区块哈希或者多个最好的区块哈希。这种情况有时被称为"弱主观性"。最后,为了保证安全,必须与最新的验证人组进行频繁的同步,时长与解绑周期一致。这样就确保了轻客戸端在因验证人解绑资金而失去任何权益之前,知道验证人组的变化情况,否则解绑的验证人就会在其绑定的高度后面开始创建新区块来实施远程攻击,以此来欺骗客户端(假设它可以控制足够多的早期私钥)。 - -注意到用这样的方式来对抗远程攻击(LRA)需要对工作量证明(proof-of-work)的原始安全模块进行彻底检查。在工作量证明中(PoW),一个轻客户端可以通过在每一个区块头中运行工作量证明,以此简便地在任何时候与可信任的创始区块的当前高度进行同步。但是,为了对抗远程攻击(LRA),我们需要轻客戸端定期上线追踪验证人组的变动,其中在首次上线时必须格外仔细地根据可靠源来验证从网络采集的信息。诚然,后面这个要求和比特币类似,其协议和软件也必须从可靠源获得。 - - -以上这些为了防止远程攻击的方法,比较好地适用于由Tendermint驱动下的区块链验证人节点以及全节点,因为这些节点需要保持与网络的连接。这些方法同样适用于希望频繁地与网络同步的轻客户端。但是,对于那些不希望频繁接入互联网或者区块链网络的轻客户端来说,还有另一种方法可以解决远程攻击的问题。非验证人节点可以在很长的解绑期内(比如比验证人的解绑期更久)使用代币作为保证金,并且为轻客戸端提供二级证明当前有效性以及过去区块哈希的解决方案。虽然这些代币对于区块链共识的安全性并没有价值,不过他们还是可以为轻客戸端提供强大的保障。如果在以太坊中支持历史区块哈希查询,那么任何人都可以用特定的智能合约来绑定他们的代币,并且提供付费证明服务,从而有效地针对轻客戸端LRA安全问题开发出一个市场。 - -### 克服分叉与审查攻击 - -由于提交区块流程的定义,任何联合后不少于⅓的投票权的节点都可以通过下线或者不广播选票来中止区块链运行。这样的联合也可以通过拒绝包含这些交易的区块来审查特定的交易,尽管这将导致大多数区块提案被拒绝,致使区块提交速率减缓,降低了它的实用性与价值。恶意的联合或许仍然会陆陆续续地广播选票,用阻挠区块链的区块提交来将其逼停,或者使用任何这些攻击的组合攻击。最终,它会通过双重签名或者违反锁定规则来造成区块链分叉。 - -如果一个全球活跃的作恶者也参与进来,就会用可能出现错误的验证组人子集导致速度降低的方法来分割网络。这不只是Tendermint面临的局限性,更确切地说是所有被活跃敌对者控制了网络的共识协议所面临的局限性1。 - - -对于这些类型的攻击,验证人的子集应该通过外部的方式进行协调,以签署选择一个分叉(及关系到的所有证据)与带有签名的验证人的初始子集的重组提案。签署了这样一份重组提案的验证者,将放弃在所有其他分叉上属于他们的保证金。客户端应在重组提案中验证签名以及任何相关的证据,并作出判断或提示终端用户作出决定。例如,一个手机钱包app应该在可能接受任何由一半以上的初始验证人们通过投票权利签署的重组提案时,给予用户安全警告提示。 - -当多于⅓的投票权益是不诚实的时候,一个非同步的拜占庭容错算法步能够达成共识,然而,分叉假设不少于⅓的投票权益已经因不正当的双重签名或者锁定改变而成为不诚实的。因此,签署重组提案是一个协调问题,任何非同步协议都无法解决这个问题(也就是自动的,并且不考虑底层网络的可靠性)。目前,我们通过互联网媒体的社会共识,把重组提案的协调问题留给了用户去协调。验证人必须在签署重组提案之前就确保没有出现网络分割的问题,以此来避免签署两个相冲突的重组提议的情况发生。 - - -假设外部协调媒介和协议是可靠的,对于分叉的担心会比审查攻击要少许多。 - - -除了需要大于⅓的拜占庭投票权益才能启动的分叉和审查制度以外,超过⅔的联合投票权益可能会提交任意、无效的状态。这是任何拜占庭容错算法的共识系统所特有的问题。与利用简单可验证证明来创建分叉的双重签名不同,检测无效状态的提交需要非验证节点来验证整个区块,这意味着非验证节点会保留一份本地的状态副本并执行每一笔交易,然后为他们自己独立计算出状态的根源。一旦检测出来,处理这类故障的唯一方法就是社会共识。打一个比方,在比特币出现问题的情况下,无论是由于软件漏洞造成的分叉(正如2013年3月),还是由于矿工拜占庭行为提交的无效状态(正如2015年7月),由商户、开发者、矿工和其他组织组成的联系紧密的社区所建立起来的社会共识会让他们按照分工来参与到修复网络的工作当中去。此外,由于Tendermint区块链的验证人身份是可识别的,那么如果需要的话,无效状态的提交实际上是可以被法律或其他外部法律体系惩治的。 - -### ABCI说明 - - -ABCI由3种主要的信息类型组成,这三类信息从共识引擎传递到应用程序上,然后应用程序用相应回复信息做出应答。 - - -`AppendTx` 信息是应用程序的主要传递媒介。区块链中的每一笔交易都通过这个信息来传递。应用程序需要验证每笔交易,这将通过接收针对当前状态、应用协议和交易密码证书的AppendTx信息来实现。验证过的交易将需要通过添加数值到键值存储或者更新UTXO数据库的方式来更新应用状态。 - - -`CheckTx`信息与AppendTx信息类似,但它只是为了交易验证。Tendermint Core的内存池会先用CheckTx验证交易有效性,并且只会将有效的交易传递给其他的节点。应用程序会检查交易序列号,如果序列号过期就会根据CheckTx返回一个错误。 - -`Commit`信息是用来计算之后会存入到下一区块头中的当前应用状态的加密提交项。这具有便利的特性。状态的前后矛盾性将会像引起程序错误,从而导致区块链分叉。这也简化了安全轻客戸端的开发,因为默克尔哈希证明可以通过检查区块哈希来加以验证,而区块哈希是由规定人数的验证人们签署的(通过投票权益)。 - - - -此外,ABCI信息允许应用程序保持追踪验证人组的改变,并让应用程序接收诸如高度和提交选票之类的区块信息。 - - -ABCI请求/响应是简单的Protobuf信息。请参考这里的[模式文件](https://github.com/tendermint/abci/blob/master/types/types.proto)。 - -##### AppendTx - * __命令行参数__: - * `Data ([]byte)`: 交易请求信息 - * __Returns__: - * `Code (uint32)`: 回复代码 - * `Data ([]byte)`: 结果字节,如果有的话 - * `Log (string)`: 错误信息 - * __使用__: - 提交并执行一笔交易,如果交易有效,那返回CodeType.OK - -##### CheckTx - * __命令行参数__: - * `Data ([]byte)`: 交易请求信息 - * __Returns__: - * `Code (uint32)`: 回复代码 - * `Data ([]byte)`: 结果字节,如果有的话 - * `Log (string)`: 错误信息 - * __使用__: - 验证一笔交易。这个信息不应该改变应用状态。交易在广播给其他节点前,首先通过CheckTx运行。你可以发起半状态化CheckTx,并在Commit or BeginBlock上清算状态,以允许序列执行同一区块中相关的交易。 - -##### Commit - * __返回值__: - * `Data ([]byte)`: 默克尔根值 - * `Log (string)`: 调试或出错信息 - * __使用__: - 返回当前应用状态。 - -##### Query - * __命令行参数__: - * `Data ([]byte)`: 请求数据 - * __返回值__: - * `Code (uint32)`: 回复代码 - * `Data ([]byte)`: 查询回复字节 - * `Log (string)`: 调试或出错信息 - -##### Flush - * __使用__: - 刷新回复队列。应用types.Application的应用程序无需实施这条信息——这个由项目进行处理。 - -##### Info - * __返回值__: - * `Data ([]byte)`: 信息字节串 - * __使用__: - 返回关于应用程序状态的信息. 应用指定。 - -##### SetOption - * __参数__: - * `Key (string)`: 设置参数 - * `Value (string)`: 参数值 - * __返回值__: - * `Log (string)`: Debug or error message - * __使用__: - 比如,针对内存池的连接可以将键设置为"mode"(模式),值为"mempool"(内存池)。或者针对共识连接,将键设置为"mode",值设置为"consensus"(共识)。其他选项根据可具体应用进行专门设置。 - -##### InitChain - * __参数__: - * `Validators ([]Validator)`: 初始化创世验证人 - * __使用__: - 在创世区块创建时调用 - -##### BeginBlock - * __参数__: - - - * * `Height (uint64)`: 区块刚开始的高度 - * __使用__: - 为新区块的开始提供信号。在附加交易(AppendTxs)前进行调用。 - -##### EndBlock - * __参数__: - * `Height (uint64)`: 结束时的区块高度 - * __返回值__: - * `Validators ([]Validator)`: 具有新选票的变动后的验证人(归零就去除) - * __使用__: - 为区块结束提供信号。在每次提交前所有交易后调用。 - -See [the ABCI repository](https://github.com/tendermint/abci#message-types) for more details - -更多细节请参考 [ABCI知识库](https://github.com/tendermint/abci#message-types)。 - -### IBC数据包交付确认 - - -发送者有很多需要接收链提供数据包交付确认的原因。比如,如果预计目的链会出错,那发送者就可能无法了解目的链的状态。或者,当目的链可能遇到因接收数据包猛烈增多而形成的拒绝服务攻击时,发送者会想要设定数据包超时时限(借助`MaxHeight` 即最大值包域)。 - - -在这些案例中,发送人可以通过在`AckPending`上设置初始数据包状态来要求提供交付确认。然后就由接收链通过包含一个简化的`IBCPacket`的应用默克尔哈希来确认交付。 - -![Figure of Zone1, Zone2, and Hub IBC with acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack.png) - - -首先,一个`IBCBlockCommit`和`IBCPacketTx`是被上传到“枢纽”上用来证明"分区1"上的`IBCPacket`的存在的。假设`IBCPacketTx`的值如下: - -- `FromChainID`: "Zone1" -- `FromBlockHeight`: 100 (假设) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 (say) - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 (假设 "枢纽" 当前高度为 300) - - `Payload`: <一个"代币"的有效负荷字节> - - -- `FromChainID`: "Zone1" -- `FromBlockHeight`: 100 (假设) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 (假设) - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 (假设"枢纽"目前的高度是300) - - `Payload`: <一个"代币"的有效负荷字节> - - -其次,一个`IBCBlockCommit` 和 `IBCPacketTx`被传输都“分区2”上用来证明`IBCPacket`在“枢纽”上的存在。假设`IBCPacketTx`的值如下: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 300 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 - - `Payload`: <一个"代币"相同的有效负荷字节> - - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 300 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 - - `Payload`: <一个"代币"相同的有效负荷字节> - - -接下来,"Zone2"必须将缩写的来显示`AckSent`的最新状态包添加到应用程序状态哈希中。 -`IBCBlockCommitand` 和`IBCPacketTx` 会传输到“枢纽"上来证明简化的`IBCPacket` 存在于"分区2"上。假设`IBCPacketTx` 的值如下: - -- `FromChainID`: "Zone2" -- `FromBlockHeight`: 400 (假设) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckSent` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <一个"代币"相同的有效负荷字节的哈希值> - - -- `FromChainID`: "Zone2" -- `FromBlockHeight`: 400 (假设) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckSent` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <一个"代币"相同的有效负荷字节的哈希值> - - - -最后,“枢纽”必须更新从`AckPending` 到`AckReceived`的数据包状态。这个新完成状态的证明应该返回到“分区2”上。假设`IBCPacketTx`的值如下: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 301 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckReceived` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <The hash bytes of the same "coin" payload> - - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 301 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckReceived` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <相同"代币"有效负荷的哈希字节> - - - -与此同时,“分区1”会假设“代币”包的交付已经成功,除非"枢纽"上有证据给出相反的证明。在上述例子中,如果"枢纽"没有从"分区2"接收到第350个区块的`AckSent` 状态,那么它就会自动将其设置为`Timeout`(超时)。这个超时的证据可以贴回到"Zone1"上,然后所有代币都会被返还。 - -![Figure of Zone1, Zone2, and Hub IBC with acknowledgement and timeout](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack_timeout.png) - -### 默克尔树及默克尔证明的说明 - -Tendermint/Cosmos生态支持的两种默克尔树:简单树和IAVL+树。 - -#### 简易版默克尔树 - - -简易版默克尔树针对基础的静态列表。如果项目的数量不是2的次方,那么有些树叶就会在不同的层上。简易树试图让树的两侧在同一高度,但是左边可能会稍大一点。这种默克尔树就是用于一个区块交易的默克尔化的,而顶层元素就是应用状态的根。 - -``` - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - - A SimpleTree with 7 elements -``` - -#### IAVL+树 - -IAVL+数据结构的目的是永久储存应用状态中的密钥对,这样就可以对确定的默克尔根哈希进行高效的运算。这个树的平衡通过 AVL算法的变体来实现,所有运行都是O(log(n))。 - -在AVL树中,任意节点的两个子树的高度至多有一处不同。无论在什么时候这种情况都是与更新相违背的,这个树都会通过创造O(log(n))新节点(指向旧树上未修改的节点)来再次达到平衡。在初始的AVL算法中,内部节点也可以保留密钥值对。AVL+算法(注意这里有个"+"号)对AVL算法进行了修改,来维持所有数值都在树叶节点上,同时还只需采用分支-节点来存储密钥。这样在维持较短的默克尔哈希轨迹对的同时,还简化了算法。 - -AVL+树类似于以太坊的[帕氏树](http://en.wikipedia.org/wiki/Radix_tree)。其中也有一定的折中。密钥不需要在嵌入到IAVL+树之前生成哈希,所以这就为密钥空间提供了较快的命令迭代,这会为很多应用程序带来好处。逻辑实现更简单,只需要内部节点和树叶节点这两种节点类型。作为一个平衡的二叉树,其默克尔证明平均更短。而另一方面,IAVL+树的默克尔根有取决于命令的更新。 -我们将支持额外有效的默克尔树,比如当二元变量可用时的以太坊帕氏树。 - - -### 交易类型 - - -在标准的执行中,交易通过ABCI界面涌入Cosmos Hub的应用程序中。 - -Cosmos Hub将接收几类主要的交易类型,包括`SendTx`, `BondTx`, `UnbondTx`, `ReportHackTx`, `SlashTx`, `BurnAtomTx`, -`ProposalCreateTx`,以及`ProposalVoteTx`(发送交易、绑定交易、解绑交易、攻击报告交易、削减交易、Atom燃烧交易,创建提案交易、以及提案投票交易),这些都不需要加以说明,会在未来版本的文档中加以备案。这里我们主要列举两个主要的IBC交易类型: `IBCBlockCommitTx` 以及`IBCPacketTx`(即IBC区块提交交易以及IBC数据包交易) - -#### IBCBlockCommitTx - - -IBCBlockCommitTx 交易主要由这些组成: - -- `ChainID (string)`: 区块链ID -- `BlockHash ([]byte)`: 区块哈希字节,就是包括应用程序哈希默克尔根 -- `BlockPartsHeader (PartSetHeader)`: 区块部分设置的头字节,只用于验证投票签名 -- `BlockHeight (int)`: 提交高度 -- `BlockRound (int)`: 提交回合 -- `Commit ([]Vote)`: 超过⅔的包括区块提交的Tendermint预提交投票 -- `ValidatorsHash ([]byte)`: 新验证组的默克尔树根哈希 -- `ValidatorsHashProof (SimpleProof)`: 在区块哈希中证明验证人哈希的简易树默克尔证明 -- `AppHash ([]byte)`: IAVL树,应用程序状态的默克尔树根哈希 -- `AppHashProof (SimpleProof)`: 在区块哈希中验证应用程序哈希的简易版默克尔树证明`AppHash` against the `BlockHash` - -#### IBCPacketTx - - -`IBCPacket` 由下列项组成: - -- `Header (IBCPacketHeader)`: 数据包头 -- `Payload ([]byte)`: 数据包有效负荷字节。可选择。 -- `PayloadHash ([]byte)`: 数据包字节哈希。可选择。 - - - -有效负荷`Payload`或有效负荷哈希`PayloadHash`必须存在一个。`IBCPacket` 的哈希就是两个项的简易版默克尔根,即头和有效负荷。没有完整有效负荷的`IBCPacket` 被称作 _缩写版包_ 。 - - - -`IBCPacketHeader`由下列项组成: - -`SrcChainID (string)`: 源区块链 ID -DstChainID (string)`: 目标区块链ID -Number (int)`: 所有数据包的唯一数字 -Status (enum)`:可以是AckPending,AckSent,AckReceived,NoAck,或Timeout任意一个 -Type (string)`: 种类根据应用程序决定。Cosmos保留"coin"(币)包种类。 -`MaxHeight (int)`: 如果状态不是这个高度给出的`NoAckWanted` 或者`AckReceived` ,那么状态就算超时。可选择。 - -An `IBCPacketTx` transaction is composed of: - -- `FromChainID (string)`: The ID of the blockchain which is providing this - packet; not necessarily the source -- `FromBlockHeight (int)`: The blockchain height in which the following packet - is included (Merkle-ized) in the block-hash of the source chain -- `Packet (IBCPacket)`: A packet of data, whose status may be one of - `AckPending`, `AckSent`, `AckReceived`, `NoAck`, or `Timeout` -- `PacketProof (IAVLProof)`: A IAVLTree Merkle-proof for proving the packet's - hash against the `AppHash` of the source chain at given height - -`IBCPacketTx` 交易有下列项组成: -- `FromChainID (string)`: 提供给这个数据包的区块链ID,不是源所必须的 -- `FromBlockHeight (int)`: 区块链高度,其中接下来的包会包含在(默克尔化的)源链的区块哈希中 -- `Packet (IBCPacket)`:数据包, 其状态可能是`AckPending`, `AckSent`, `AckReceived`, `NoAck`, 或者 `Timeout`其中的一个 -- `PacketProof (IAVLProof)`: IAVL树默克尔证明,用于验证在给定高度下的源链应用哈希中的数据包哈希 - - -通过"Hub",将数据包从"Zone1"发送到"Zone2"的序列,描述在{Figure X}函数中。首先,一个`IBCPacketTx`会向"Hub"证明数据包是包含在"Zone1"的应用程序状态中。然后,另一个`IBCPacketTx` 会向"Zone2"证明数据包包含在"Hub"的应用程序状态中。在这个过程中,`IBCPacketTx` 的字段是相同的:`SrcChainID`永远是"Zone1",而`DstChainID` 永远是"Zone2"。 - -The `PacketProof` must have the correct Merkle-proof path, as follows: - -`PacketProof` 必须有正确的默克尔证明路径,如下: - -``` -IBC/<SrcChainID>/<DstChainID>/<Number> - -``` - - -当“Zone1”要通过“Hub”将数据包传送到“Zone2”中,无论数据包是否在“Zone1”、“Hub”、或者“Zone2”中默克尔化了,`IBCPacket`数据都是相同的。唯一易变的字段是为追踪交付的`Status`。 - -## 鸣谢 ############################################################ - -我们为所有朋友欲同行们在概念成型与检查方面给予的帮助,以及对我们在Tendermint与Cosmos工作中的大力支持,表示衷心地感谢。 - -* [Zaki Manian](https://github.com/zmanian) of - [SkuChain](https://www.skuchain.com/) provided much help in formatting and -wording, especially under the ABCI section -* [Jehan Tremback](https://github.com/jtremback) of Althea and Dustin Byington - for helping with initial iterations -* [Andrew Miller](http://soc1024.com/) of [Honey - Badger](https://eprint.iacr.org/2016/199) for feedback on consensus -* [Greg Slepak](https://fixingtao.com/) for feedback on consensus and wording -* Also thanks to [Bill Gleim](https://github.com/gleim) and [Seunghwan - Han](http://www.seunghwanhan.com) for various contributions. -* __Your name and organization here for your contribution__ - -* [SkuChain](https://www.skuchain.com/)的[Zaki Manian](https://github.com/zmanian)在格式与措辞方面提供了很多帮助,尤其在ABCI部分。 -* Althea的[Jehan Tremback](https://github.com/jtremback)和Dustin Byington在初始迭代方面的帮助。 -* [Honey - Badger](https://eprint.iacr.org/2016/199)的 [Andrew Miller](http://soc1024.com/) 在共识部分给予的反馈。 -* [Greg Slepak](https://fixingtao.com/)对共识部分的反馈以及在措辞方面的帮助。 -* 同时还要感谢 [Bill Gleim](https://github.com/gleim)和 [Seunghwan - Han](http://www.seunghwanhan.com)在多方面的支持与贡献。 -* **此处还有您及您的组织对本文的贡献。 - -## 引用 - -[1]: https://bitcoin.org/bitcoin.pdf -[2]: http://zerocash-project.org/paper -[3]: https://github.com/ethereum/wiki/wiki/White-Paper -[4]: https://download.slock.it/public/DAO/WhitePaper.pdf -[5]: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki -[6]: https://arxiv.org/pdf/1510.02037v2.pdf -[7]: https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf -[8]: https://github.com/tendermint/tendermint/wiki -[9]: https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf -[10]: https://blog.ethereum.org/2014/01/15/slasher-a-punitive-proof-of-stake-algorithm/ -[11]: http://pmg.csail.mit.edu/papers/osdi99.pdf -[12]: https://bitshares.org/technology/delegated-proof-of-stake-consensus/ -[13]: https://www.stellar.org/papers/stellar-consensus-protocol.pdf -[14]: https://interledger.org/rfcs/0001-interledger-architecture/ -[15]: https://blockstream.com/sidechains.pdf -[16]: https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/ -[17]: https://github.com/tendermint/abci -[18]: https://github.com/ethereum/EIPs/issues/53 -[19]: http://www.ds.ewi.tudelft.nl/fileadmin/pds/papers/PerformanceAnalysisOfLibswift.pdf -[20]: http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf -[21]: https://en.bitcoin.it/wiki/Thin_Client_Security -[22]: http://vitalik.ca/files/mauve_paper.html - -* [1] Bitcoin: https://bitcoin.org/bitcoin.pdf -* [2] ZeroCash: http://zerocash-project.org/paper -* [3] Ethereum: https://github.com/ethereum/wiki/wiki/White-Paper -* [4] TheDAO: https://download.slock.it/public/DAO/WhitePaper.pdf -* [5] Segregated Witness: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki -* [6] BitcoinNG: https://arxiv.org/pdf/1510.02037v2.pdf -* [7] Lightning Network: https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf -* [8] Tendermint: https://github.com/tendermint/tendermint/wiki -* [9] FLP Impossibility: https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf -* [10] Slasher: https://blog.ethereum.org/2014/01/15/slasher-a-punitive-proof-of-stake-algorithm/ -* [11] PBFT: http://pmg.csail.mit.edu/papers/osdi99.pdf -* [12] BitShares: https://bitshares.org/technology/delegated-proof-of-stake-consensus/ -* [13] Stellar: https://www.stellar.org/papers/stellar-consensus-protocol.pdf -* [14] Interledger: https://interledger.org/rfcs/0001-interledger-architecture/ -* [15] Sidechains: https://blockstream.com/sidechains.pdf -* [16] Casper: https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/ -* [17] ABCI: https://github.com/tendermint/abci -* [18] Ethereum Sharding: https://github.com/ethereum/EIPs/issues/53 -* [19] LibSwift: http://www.ds.ewi.tudelft.nl/fileadmin/pds/papers/PerformanceAnalysisOfLibswift.pdf -* [20] DLS: http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf -* [21] Thin Client Security: https://en.bitcoin.it/wiki/Thin_Client_Security -* [22] Ethereum 2.0 Mauve Paper: http://vitalik.ca/files/mauve_paper.html - -#### 未分类链接 - -* https://www.docdroid.net/ec7xGzs/314477721-ethereum-platform-review-opportunities-and-challenges-for-private-and-consortium-blockchains.pdf.html diff --git a/docs/resources/whitepaper.md b/docs/resources/whitepaper.md deleted file mode 100644 index f77608072d70..000000000000 --- a/docs/resources/whitepaper.md +++ /dev/null @@ -1,1590 +0,0 @@ -# Cosmos - -A Network of Distributed Ledgers - -Jae Kwon <mailto:jae@tendermint.com><br/> -Ethan Buchman <mailto:ethan@tendermint.com> - -For discussions, [join our community chat](https://riot.im/app/#/room/#cosmos:matrix.org)! - -_NOTE: If you can read this on GitHub, then we're still actively developing this -document. Please check regularly for updates!_ - -\[[toc]] - -## Introduction - -The combined success of the open-source ecosystem, decentralized -file-sharing, and public cryptocurrencies has inspired an understanding that -decentralized internet protocols can be used to radically improve socio-economic -infrastructure. We have seen specialized blockchain applications like Bitcoin -[\[1\]][1] (a cryptocurrency), Zerocash [\[2\]][2] (a cryptocurrency for -privacy), and generalized smart contract platforms such as Ethereum [\[3\]][3], -with countless distributed applications for the Ethereum Virtual Machine (EVM) such as Augur (a prediction -market) and TheDAO [\[4\]][4] (an investment club). - -To date, however, these blockchains have suffered from a number of drawbacks, -including their gross energy inefficiency, poor or limited performance, and -immature governance mechanisms. Proposals to scale -Bitcoin's transaction throughput, such as Segregated-Witness [\[5\]][5] and -BitcoinNG [\[6\]][6], are vertical scaling solutions that remain -limited by the capacity of a single physical machine, in order to ensure the -property of complete auditability. The Lightning Network [\[7\]][7] can help -scale Bitcoin transaction volume by leaving some transactions off the ledger -completely, and is well suited for micropayments and privacy-preserving payment -rails, but may not be suitable for more generalized scaling needs. - -An ideal solution is one that allows multiple parallel blockchains to -interoperate while retaining their security properties. This has proven -difficult, if not impossible, with proof-of-work. Merged mining, for instance, -allows the work done to secure a parent chain to be reused on a child chain, -but transactions must still be validated, in order, by each node, and a -merge-mined blockchain is vulnerable to attack if a majority of the hashing -power on the parent is not actively merge-mining the child. An academic review -of [alternative blockchain network -architectures](http://vukolic.com/iNetSec_2015.pdf) is provided for additional -context, and we provide summaries of other proposals and their drawbacks in -[Related Work](#related-work). - -Here we present Cosmos, a novel blockchain network architecture that addresses all -of these problems. Cosmos is a network of many independent blockchains, called -zones. The zones are powered by Tendermint Core [\[8\]][8], which provides a -high-performance, consistent, secure -[PBFT-like](https://blog.cosmos.network/tendermint-vs-pbft-12e9f294c9ab?gi=1777e47b6fc6) consensus engine, -where strict [fork-accountability](#fork-accountability) guarantees hold over -the behaviour of malicious actors. Tendermint Core's BFT consensus algorithm is -well suited for scaling public proof-of-stake blockchains. - -The first zone on Cosmos is called the Cosmos Hub. The Cosmos Hub is a -multi-asset proof-of-stake cryptocurrency with a simple governance mechanism -which enables the network to adapt and upgrade. In addition, the Cosmos Hub can be -extended by connecting other zones. - -The hub and zones of the Cosmos network communicate with each other via an -inter-blockchain communication (IBC) protocol, a kind of virtual UDP or TCP for -blockchains. Tokens can be transferred from one zone to another securely and -quickly without the need for exchange liquidity between zones. Instead, all -inter-zone token transfers go through the Cosmos Hub, which keeps track of the -total amount of tokens held by each zone. The hub isolates each zone from the -failure of other zones. Because anyone can connect a new zone to the Cosmos Hub, -zones allow for future-compatibility with new blockchain innovations. - -## Tendermint - -In this section we describe the Tendermint consensus protocol and the interface -used to build applications with it. For more details, see the [appendix](#appendix). - -### Validators - -In classical Byzantine fault-tolerant (BFT) algorithms, each node has the same -weight. In Tendermint, nodes have a non-negative amount of _voting power_, and -nodes that have positive voting power are called _validators_. Validators -participate in the consensus protocol by broadcasting cryptographic signatures, -or _votes_, to agree upon the next block. - -Validators' voting powers are determined at genesis, or are changed -deterministically by the blockchain, depending on the application. For example, -in a proof-of-stake application such as the Cosmos Hub, the voting power may be -determined by the amount of staking tokens bonded as collateral. - -_NOTE: Fractions like ⅔ and ⅓ refer to fractions of the total voting power, -never the total number of validators, unless all the validators have equal -weight. >⅔ means "more than ⅔", ≥⅓ means "at least ⅓"._ - -### Consensus - -Tendermint is a partially synchronous BFT consensus protocol derived from the -DLS consensus algorithm [\[20\]][20]. Tendermint is notable for its simplicity, -performance, and [fork-accountability](#fork-accountability). The protocol -requires a fixed known set of validators, where each validator is identified by -their public key. Validators attempt to come to consensus on one block at a time, -where a block is a list of transactions. Voting for consensus on a block proceeds in -rounds. Each round has a round-leader, or proposer, who proposes a block. The -validators then vote, in stages, on whether to accept the proposed block -or move on to the next round. The proposer for a round is chosen -deterministically from the ordered list of validators, in proportion to their -voting power. - -The full details of the protocol are described -[here](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - -Tendermint’s security derives from its use of optimal Byzantine fault-tolerance -via super-majority (>⅔) voting and a locking mechanism. Together, they ensure -that: - -- ≥⅓ voting power must be Byzantine to cause a violation of safety, where more - than two values are committed. -- if any set of validators ever succeeds in violating safety, or even attempts - to do so, they can be identified by the protocol. This includes both voting - for conflicting blocks and broadcasting unjustified votes. - -Despite its strong guarantees, Tendermint provides exceptional performance. In -benchmarks of 64 nodes distributed across 7 datacenters on 5 continents, on -commodity cloud instances, Tendermint consensus can process thousands of -transactions per second, with commit latencies on the order of one to two -seconds. Notably, performance of well over a thousand transactions per second -is maintained even in harsh adversarial conditions, with validators crashing or -broadcasting maliciously crafted votes. See the figure below for details. - -![Figure of Tendermint throughput performance](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/tendermint_throughput_blocksize.png) - -### Light Clients - -A major benefit of Tendermint's consensus algorithm is simplified light client -security, making it an ideal candidate for mobile and internet-of-things use -cases. While a Bitcoin light client must sync chains of block headers and find -the one with the most proof of work, Tendermint light clients need only to keep -up with changes to the validator set, and then verify the >⅔ PreCommits -in the latest block to determine the latest state. - -Succinct light client proofs also enable [inter-blockchain -communication](#inter-blockchain-communication-ibc). - -### Preventing Attacks - -Tendermint has protective measures for preventing certain notable -attacks, like [long-range-nothing-at-stake double -spends](#preventing-long-range-attacks) and -[censorship](#overcoming-forks-and-censorship-attacks). These are discussed more -fully in the [appendix](#appendix). - -### ABCI - -The Tendermint consensus algorithm is implemented in a program called Tendermint -Core. Tendermint Core is an application-agnostic "consensus engine" that can -turn any deterministic blackbox application into a distributedly replicated -blockchain. Tendermint Core connects to blockchain -applications via the Application Blockchain Interface (ABCI) [\[17\]][17]. Thus, ABCI -allows for blockchain applications to be programmed in any language, not just -the programming language that the consensus engine is written in. Additionally, -ABCI makes it possible to easily swap out the consensus layer of any existing -blockchain stack. - -We draw an analogy with the well-known cryptocurrency Bitcoin. Bitcoin is a -cryptocurrency blockchain where each node maintains a fully audited Unspent -Transaction Output (UTXO) database. If one wanted to create a Bitcoin-like -system on top of ABCI, Tendermint Core would be responsible for - -- Sharing blocks and transactions between nodes -- Establishing a canonical/immutable order of transactions (the blockchain) - -Meanwhile, the ABCI application would be responsible for - -- Maintaining the UTXO database -- Validating cryptographic signatures of transactions -- Preventing transactions from spending non-existent funds -- Allowing clients to query the UTXO database - -Tendermint is able to decompose the blockchain design by offering a very simple -API between the application process and consensus process. - -## Cosmos Overview - -Cosmos is a network of independent parallel blockchains that are each powered by -classical BFT consensus algorithms like Tendermint -[1](https://github.com/tendermint/tendermint). - -The first blockchain in this network will be the Cosmos Hub. The Cosmos Hub -connects to many other blockchains (or _zones_) via a novel inter-blockchain -communication protocol. The Cosmos Hub tracks numerous token types and keeps -record of the total number of tokens in each connected zone. Tokens can be -transferred from one zone to another securely and quickly without the need for -a liquid exchange between zones, because all inter-zone coin transfers go -through the Cosmos Hub. - -This architecture solves many problems that the blockchain space faces today, -such as application interoperability, scalability, and seamless upgradability. -For example, zones derived from Bitcoind, Go-Ethereum, CryptoNote, ZCash, or any -blockchain system can be plugged into the Cosmos Hub. These zones allow Cosmos -to scale infinitely to meet global transaction demand. Zones are also a great -fit for a distributed exchange, which will be supported as well. - -Cosmos is not just a single distributed ledger, and the Cosmos Hub isn't a -walled garden or the center of its universe. We are designing a protocol for -an open network of distributed ledgers that can serve as a new foundation for -future financial systems, based on principles of cryptography, sound economics, -consensus theory, transparency, and accountability. - -### Tendermint-BFT - -The Cosmos Hub is the first public blockchain in the Cosmos Network, powered by -Tendermint's BFT consensus algorithm. The Tendermint open-source project was -born in 2014 to address the speed, scalability, and environmental issues of -Bitcoin's proof-of-work consensus algorithm. By using and improving upon -proven BFT algorithms developed at MIT in 1988 [\[20\]][20], the Tendermint -team was the first to conceptually demonstrate a proof-of-stake cryptocurrency -that addresses the nothing-at-stake problem suffered by first-generation -proof-of-stake cryptocurrencies such as NXT and BitShares1.0. - -Today, practically all Bitcoin mobile wallets use trusted servers to provide -them with transaction verification. This is because proof-of-work requires -waiting for many confirmations before a transaction can be considered -irreversibly committed. Double-spend attacks have already been demonstrated on -services like CoinBase. - -Unlike other blockchain consensus systems, Tendermint offers instant and -provably secure mobile-client payment verification. Since the Tendermint is -designed to never fork at all, mobile wallets can receive instant transaction -confirmation, which makes trustless and practical payments a reality on -smartphones. This has significant ramifications for Internet of Things applications as well. - -Validators in Cosmos have a similar role to Bitcoin miners, but instead use -cryptographic signatures to vote. Validators are secure, dedicated machines -that are responsible for committing blocks. Non-validators can delegate their -staking tokens (called "atoms") to any validator to earn a portion of block fees -and atom rewards, but they incur the risk of getting punished (slashed) if the -delegate validator gets hacked or violates the protocol. The proven safety -guarantees of Tendermint BFT consensus, and the collateral deposit of -stakeholders--validators and delegators--provide provable, quantifiable -security for nodes and light clients. - -### Governance - -Distributed public ledgers should have a constitution and a governance system. -Bitcoin relies on the Bitcoin Foundation and mining to -coordinate upgrades, but this is a slow process. Ethereum split into ETH and -ETC after hard-forking to address TheDAO hack, largely because there was no -prior social contract nor mechanism for making such decisions. - -Validators and delegators on the Cosmos Hub can vote on proposals that can -change preset parameters of the system automatically (such as the block gas -limit), coordinate upgrades, as well as vote on amendments to the human-readable -constitution that govern the policies of the Cosmos Hub. The constitution -allows for cohesion among the stakeholders on issues such as theft -and bugs (such as TheDAO incident), allowing for quicker and cleaner resolution. - -Each zone can also have their own constitution and governance mechanism as well. -For example, the Cosmos Hub could have a constitution that enforces immutability -at the Hub (no roll-backs, save for bugs of the Cosmos Hub node implementation), -while each zone can set their own policies regarding roll-backs. - -By enabling interoperability among differing policy zones, the Cosmos network -gives its users ultimate freedom and potential for permissionless -experimentation. - -## The Hub and Zones - -Here we describe a novel model of decentralization and scalability. Cosmos is a -network of many blockchains powered by Tendermint. While existing proposals aim -to create a "single blockchain" with total global transaction ordering, Cosmos -permits many blockchains to run concurrently with one another while retaining -interoperability. - -At the basis, the Cosmos Hub manages many independent blockchains called "zones" -(sometimes referred to as "shards", in reference to the database scaling -technique known as "sharding"). A constant stream of recent block commits from -zones posted on the Hub allows the Hub to keep up with the state of each zone. -Likewise, each zone keeps up with the state of the Hub (but zones do not keep up -with each other except indirectly through the Hub). Packets of information are -then communicated from one zone to another by posting Merkle-proofs as evidence -that the information was sent and received. This mechanism is called -inter-blockchain communication, or IBC for short. - -![Figure of hub and zones -acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/images/hub_and_zones.png) - -Any of the zones can themselves be hubs to form an acyclic graph, but -for the sake of clarity we will only describe the simple configuration where -there is only one hub, and many non-hub zones. - -### The Hub - -The Cosmos Hub is a blockchain that hosts a multi-asset distributed ledger, -where tokens can be held by individual users or by zones themselves. These -tokens can be moved from one zone to another in a special IBC packet called a -"coin packet". The hub is responsible for preserving the global invariance of -the total amount of each token across the zones. IBC coin packet transactions -must be committed by the sender, hub, and receiver blockchains. - -Since the Cosmos Hub acts as the central ledger for the whole -system, the security of the Hub is of paramount importance. While each -zone may be a Tendermint blockchain that is secured by as few as 4 (or even -less if BFT consensus is not needed), the Hub must be secured by a globally -decentralized set of validators that can withstand the most severe attack -scenarios, such as a continental network partition or a nation-state sponsored -attack. - -### The Zones - -A Cosmos zone is an independent blockchain that exchanges IBC messages with the -Hub. From the Hub's perspective, a zone is a multi-asset dynamic-membership -multi-signature account that can send and receive tokens using IBC packets. Like -a cryptocurrency account, a zone cannot transfer more tokens than it has, but -can receive tokens from others who have them. A zone may be designated as an -"source" of one or more token types, granting it the power to inflate that token -supply. - -Atoms of the Cosmos Hub may be staked by validators of a zone connected to the -Hub. While double-spend attacks on these zones would result in the slashing of -atoms with Tendermint's fork-accountability, a zone where >⅔ of the voting power -are Byzantine can commit invalid state. The Cosmos Hub does not verify or -execute transactions committed on other zones, so it is the responsibility of -users to send tokens to zones that they trust. In the future, the Cosmos Hub's -governance system may pass Hub improvement proposals that account for zone -failures. For example, outbound token transfers from some (or all) zones may be -throttled to allow for the emergency circuit-breaking of zones (a temporary halt -of token transfers) when an attack is detected. - -## Inter-blockchain Communication (IBC) - -Now we look at how the Hub and zones communicate with each other. For example, if -there are three blockchains, "Zone1", "Zone2", and "Hub", and we wish for -"Zone1" to produce a packet destined for "Zone2" going through "Hub". To move a -packet from one blockchain to another, a proof is posted on the -receiving chain. The proof states that the sending chain published a packet for the alleged -destination. For the receiving chain to check this proof, it must be able keep -up with the sender's block headers. This mechanism is similar to that used by -sidechains, which requires two interacting chains to be aware of one another via a -bidirectional stream of proof-of-existence datagrams (transactions). - -The IBC protocol can naturally be defined using two types of transactions: an -`IBCBlockCommitTx` transaction, which allows a blockchain to prove to any -observer of its most recent block-hash, and an `IBCPacketTx` transaction, which -allows a blockchain to prove to any observer that the given packet was indeed -published by the sender's application, via a Merkle-proof to the recent -block-hash. - -By splitting the IBC mechanics into two separate transactions, we allow the -native fee market-mechanism of the receiving chain to determine which packets -get committed (i.e. acknowledged), while allowing for complete freedom on the -sending chain as to how many outbound packets are allowed. - -![Figure of Zone1, Zone2, and Hub IBC without -acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_without_ack.png) - -In the example above, in order to update the block-hash of -"Zone1" on "Hub" (or of "Hub" on "Zone2"), an `IBCBlockCommitTx` -transaction must be posted on "Hub" with the block-hash of "Zone1" (or on -"Zone2" with the block-hash of "Hub"). - -_See [IBCBlockCommitTx](#ibcblockcommittx) and [IBCPacketTx](#ibcpacketcommit) -for for more information on the two IBC transaction types._ - -## Use Cases - -### Distributed Exchange - -In the same way that Bitcoin is more secure by being a distributed, -mass-replicated ledger, we can make exchanges less vulnerable to external and -internal hacks by running it on the blockchain. We call this a distributed -exchange. - -What the cryptocurrency community calls a decentralized exchange today are -based on something called "atomic cross-chain" (AXC) transactions. With an AXC -transaction, two users on two different chains can make two transfer -transactions that are committed together on both ledgers, or none at all (i.e. -atomically). For example, two users can trade bitcoins for ether (or any two -tokens on two different ledgers) using AXC transactions, even though Bitcoin -and Ethereum are not connected to each other. The benefit of running an -exchange on AXC transactions is that neither users need to trust each other or -the trade-matching service. The downside is that both parties need to be -online for the trade to occur. - -Another type of decentralized exchange is a mass-replicated distributed -exchange that runs on its own blockchain. Users on this kind of exchange can -submit a limit order and turn their computer off, and the trade can execute -without the user being online. The blockchain matches and completes the trade -on behalf of the trader. - -A centralized exchange can create a deep orderbook of limit orders and thereby -attract more traders. Liquidity begets more liquidity in the exchange world, -and so there is a strong network effect (or at least a winner-take-most effect) -in the exchange business. The current leader for cryptocurrency exchanges -today is Poloniex with a 24-hour volume of $20M, and in second place is -Bitfinex with a 24-hour volume of $5M. Given such strong network effects, it -is unlikely for AXC-based decentralized exchanges to win volume over the -centralized exchanges. For a decentralized exchange to compete with a -centralized exchange, it would need to support deep orderbooks with limit -orders. Only a distributed exchange on a blockchain can provide that. - -Tendermint provides additional benefits of faster transaction commits. By -prioritizing fast finality without sacrificing consistency, zones in Cosmos can -finalize transactions fast -- for both exchange order transactions as well as -IBC token transfers to and from other zones. - -Given the state of cryptocurrency exchanges today, a great application for -Cosmos is the distributed exchange (aka the Cosmos DEX). The transaction -throughput capacity as well as commit latency can be comparable to those of -centralized exchanges. Traders can submit limit orders that can be executed -without both parties having to be online. And with Tendermint, the Cosmos hub, -and IBC, traders can move funds in and out of the exchange to and from other -zones with speed. - -### Bridging to Other Cryptocurrencies - -A privileged zone can act as the source of a bridged token of another -cryptocurrency. A bridge is similar to the relationship between a -Cosmos hub and zone; both must keep up with the latest blocks of the -other in order to verify proofs that tokens have moved from one to the other. A -"bridge-zone" on the Cosmos network keeps up with the Hub as well as the -other cryptocurrency. The indirection through the bridge-zone allows the logic of -the Hub to remain simple and agnostic to other blockchain consensus strategies -such as Bitcoin's proof-of-work mining. - -#### Sending Tokens to the Cosmos Hub - -Each bridge-zone validator would run a Tendermint-powered blockchain with a special -ABCI bridge-app, but also a full-node of the "origin" blockchain. - -When new blocks are mined on the origin, the bridge-zone validators will come -to agreement on committed blocks by signing and sharing their respective local -view of the origin's blockchain tip. When a bridge-zone receives payment on the -origin (and sufficient confirmations were agreed to have been seen in the case -of a PoW chain such as Ethereum or Bitcoin), a corresponding account is created -on the bridge-zone with that balance. - -In the case of Ethereum, the bridge-zone can share the same validator-set as the -Cosmos Hub. On the Ethereum side (the origin), a bridge-contract would allow -ether holders to send ether to the bridge-zone by sending it to the bridge-contract -on Ethereum. Once ether is received by the bridge-contract, the ether cannot be -withdrawn unless an appropriate IBC packet is received by the bridge-contract from -the bridge-zone. The bridge-contract tracks the validator-set of the bridge-zone, which -may be identical to the Cosmos Hub's validator-set. - -In the case of Bitcoin, the concept is similar except that instead of a single -bridge-contract, each UTXO would be controlled by a threshold multisignature P2SH -pubscript. Due to the limitations of the P2SH system, the signers cannot be -identical to the Cosmos Hub validator-set. - -#### Withdrawing Tokens from Cosmos Hub - -Ether on the bridge-zone ("bridged-ether") can be transferred to and from the -Hub, and later be destroyed with a transaction that sends it to a particular -withdrawal address on Ethereum. An IBC packet proving that the transaction -occurred on the bridge-zone can be posted to the Ethereum bridge-contract to -allow the ether to be withdrawn. - -In the case of Bitcoin, the restricted scripting system makes it difficult to -mirror the IBC coin-transfer mechanism. Each UTXO has its own independent -pubscript, so every UTXO must be migrated to a new UTXO when there is a change -in the set of Bitcoin escrow signers. One solution is to compress and -decompress the UTXO-set as necessary to keep the total number of UTXOs down. - -#### Total Accountability of Bridge Zones - -The risk of such a bridgeging contract is a rogue validator set. ≥⅓ Byzantine -voting power could cause a fork, withdrawing ether from the bridge-contract on -Ethereum while keeping the bridged-ether on the bridge-zone. Worse, >⅔ Byzantine -voting power can steal ether outright from those who sent it to the -bridge-contract by deviating from the original bridgeging logic of the bridge-zone. - -It is possible to address these issues by designing the bridge to be totally -accountable. For example, all IBC packets, from the hub and the origin, might -require acknowledgement by the bridge-zone in such a way that all state -transitions of the bridge-zone can be efficiently challenged and verified by -either the hub or the origin's bridge-contract. The Hub and the origin should -allow the bridge-zone validators to post collateral, and token transfers out of -the bridge-contract should be delayed (and collateral unbonding period -sufficiently long) to allow for any challenges to be made by independent -auditors. We leave the design of the specification and implementation of this -system open as a future Cosmos improvement proposal, to be passed by the Cosmos -Hub's governance system. - -### Ethereum Scaling - -Solving the scaling problem is an open issue for Ethereum. Currently, -Ethereum nodes process every single transaction and also store all the states. -[link](https://docs.google.com/presentation/d/1CjD0W4l4-CwHKUvfF5Vlps76fKLEC6pIwu1a_kC_YRQ/mobilepresent?slide=id.gd284b9333_0_28). - -Since Tendermint can commit blocks much faster than Ethereum's proof-of-work, -EVM zones powered by Tendermint consensus and operating on bridged-ether can -provide higher performance to Ethereum blockchains. Additionally, though the -Cosmos Hub and IBC packet mechanics does not allow for arbitrary contract logic -execution per se, it can be used to coordinate token movements between Ethereum -contracts running on different zones, providing a foundation for token-centric -Ethereum scaling via sharding. - -### Multi-Application Integration - -Cosmos zones run arbitrary application logic, which is defined at the beginning of the -zone's life and can potentially be updated over time by governance. Such flexibility -allows Cosmos zones to act as bridges to other cryptocurrencies such as Ethereum or -Bitcoin, and it also permits derivatives of those blockchains, utilizing the -same codebase but with a different validator set and initial distribution. This -allows many existing cryptocurrency frameworks, such as those of Ethereum, -Zerocash, Bitcoin, CryptoNote and so on, to be used with Tendermint Core, -which is a higher performance consensus engine, on a common network, opening tremendous -opportunity for interoperability across platforms. Furthermore, as a -multi-asset blockchain, a single transaction may contain multiple inputs and -outputs, where each input can be any token type, enabling Cosmos to serve -directly as a platform for decentralized exchange, though orders are assumed to -be matched via other platforms. Alternatively, a zone can serve as a distributed -fault-tolerant exchange (with orderbooks), which can be a strict improvement -over existing centralized cryptocurrency exchanges which tend to get hacked over -time. - -Zones can also serve as blockchain-backed versions of enterprise and government -systems, where pieces of a particular service that are traditionally run by an -organization or group of organizations are instead run as a ABCI application on -a certain zone, which allows it to inherit the security and interoperability of the -public Cosmos network without sacrificing control over the underlying service. -Thus, Cosmos may offer the best of both worlds for organizations looking to -utilize blockchain technology but who are wary of relinquishing control completely -to a distributed third party. - -### Network Partition Mitigation - -Some claim that a major problem with consistency-favouring consensus algorithms -like Tendermint is that any network partition which causes there to be no single -partition with >⅔ voting power (e.g. ≥⅓ going offline) will halt consensus -altogether. The Cosmos architecture can help mitigate this problem by using a global -hub with regional autonomous zones, where voting power for each zone are -distributed based on a common geographic region. For instance, a common -paradigm may be for individual cities, or regions, to operate their own zones -while sharing a common hub (e.g. the Cosmos Hub), enabling municipal activity to -persist in the event that the hub halts due to a temporary network partition. -Note that this allows real geological, political, and network-topological -features to be considered in designing robust federated fault-tolerant systems. - -### Federated Name Resolution System - -NameCoin was one of the first blockchains to attempt to solve the -name-resolution problem by adapting the Bitcoin blockchain. Unfortunately there -have been several issues with this approach. - -With Namecoin, we can verify that, for example, <em>@satoshi</em> was registered with a -particular public key at some point in the past, but we wouldn’t know whether -the public key had since been updated recently unless we download all the blocks -since the last update of that name. This is due to the limitation of Bitcoin's -UTXO transaction Merkle-ization model, where only the transactions (but not -mutable application state) are Merkle-ized into the block-hash. This lets us -prove existence, but not the non-existence of later updates to a name. Thus, we -can't know for certain the most recent value of a name without trusting a full -node, or incurring significant costs in bandwidth by downloading the whole -blockchain. - -Even if a Merkle-ized search tree were implemented in NameCoin, its dependency -on proof-of-work makes light client verification problematic. Light clients must -download a complete copy of the headers for all blocks in the entire blockchain -(or at least all the headers since the last update to a name). This means that -the bandwidth requirements scale linearly with the amount of time [\[21\]][21]. -In addition, name-changes on a proof-of-work blockchain requires waiting for -additional proof-of-work confirmation blocks, which can take up to an hour on -Bitcoin. - -With Tendermint, all we need is the most recent block-hash signed by a quorum of -validators (by voting power), and a Merkle proof to the current value associated -with the name. This makes it possible to have a succinct, quick, and secure -light-client verification of name values. - -In Cosmos, we can take this concept and extend it further. Each -name-registration zone in Cosmos can have an associated top-level-domain -(TLD) name such as ".com" or ".org", and each name-registration zone can have -its own governance and registration rules. - -## Issuance and Incentives - -### The Atom Token - -While the Cosmos Hub is a multi-asset distributed ledger, there is a special -native token called the _atom_. Atoms are the only staking token of the Cosmos -Hub. Atoms are a license for the holder to vote, validate, or delegate to other -validators. Like Ethereum's ether, atoms can also be used to pay for -transaction fees to mitigate spam. Additional inflationary atoms and block -transaction fees are rewarded to validators and delegators who delegate to -validators. - -The `BurnAtomTx` transaction can be used to recover any proportionate amount of -tokens from the reserve pool. - -#### Fundraiser - -The initial distribution of atom tokens and validators on Genesis will go to the -donors of the Cosmos Fundraiser (75%), lead donors (5%), Cosmos Network -Foundation (10%), and ALL IN BITS, Inc (10%). From genesis onward, 1/3 of the -total amount of atoms will be rewarded to bonded validators and delegators -every year. - -See the [Cosmos Plan](https://github.com/cosmos/cosmos/blob/master/PLAN.md) -for additional details. - -### Limitations on the Number of Validators - -Unlike Bitcoin or other proof-of-work blockchains, a Tendermint blockchain gets -slower with more validators due to the increased communication complexity. -Fortunately, we can support enough validators to make for a robust globally -distributed blockchain with very fast transaction confirmation times, and, as -bandwidth, storage, and parallel compute capacity increases, we will be able to -support more validators in the future. - -On genesis day, the maximum number of validators will be set to 100, and this -number will increase at a rate of 13% for 10 years, and settle at 300 -validators. - - Year 0: 100 - Year 1: 113 - Year 2: 127 - Year 3: 144 - Year 4: 163 - Year 5: 184 - Year 6: 208 - Year 7: 235 - Year 8: 265 - Year 9: 300 - Year 10: 300 - ... - -### Becoming a Validator After Genesis Day - -Atom holders who are not already can become validators by signing and -submitting a `BondTx` transaction. The amount of atoms provided as collateral -must be nonzero. Anyone can become a validator at any time, except when the -size of the current validator set is greater than the maximum number of -validators allowed. In that case, the transaction is only valid if the amount -of atoms is greater than the amount of effective atoms held by the smallest -validator, where effective atoms include delegated atoms. When a new validator -replaces an existing validator in such a way, the existing validator becomes -inactive and all the atoms and delegated atoms enter the unbonding state. - -### Penalties for Validators - -There must be some penalty imposed on the validators for any intentional -or unintentional deviation from the sanctioned protocol. Some evidence is -immediately admissible, such as a double-sign at the same height and round, or a -violation of "prevote-the-lock" (a rule of the Tendermint consensus protocol). -Such evidence will result in the validator losing its good standing and its -bonded atoms as well its proportionate share of tokens in the reserve pool -- -collectively called its "stake" -- will get slashed. - -Sometimes, validators will not be available, either due to regional network -disruptions, power failure, or other reasons. If, at any point in the past -`ValidatorTimeoutWindow` blocks, a validator's commit vote is not included in -the blockchain more than `ValidatorTimeoutMaxAbsent` times, that validator will -become inactive, and lose `ValidatorTimeoutPenalty` (DEFAULT 1%) of its stake. - -Some "malicious" behavior does not produce obviously discernable evidence on the -blockchain. In these cases, the validators can coordinate out of band to force -the timeout of these malicious validators, if there is a supermajority -consensus. - -In situations where the Cosmos Hub halts due to a ≥⅓ coalition of voting power -going offline, or in situations where a ≥⅓ coalition of voting power censor -evidence of malicious behavior from entering the blockchain, the hub must -recover with a hard-fork reorg-proposal. (Link to "Forks and Censorship -Attacks"). - -### Transaction Fees - -Cosmos Hub validators can accept any token type or combination of types as fees -for processing a transaction. Each validator can subjectively set whatever -exchange rate it wants, and choose whatever transactions it wants, as long as -the `BlockGasLimit` is not exceeded. The collected fees, minus any taxes -specified below, are redistributed to the bonded stakeholders in proportion to -their bonded atoms, every `ValidatorPayoutPeriod` (DEFAULT 1 hour). - -Of the collected transaction fees, `ReserveTax` (DEFAULT 2%) will go toward the -reserve pool to increase the reserve pool and increase the security and value of -the Cosmos network. These funds can also be distributed in accordance with the -decisions made by the governance system. - -Atom holders who delegate their voting power to other validators pay a -commission to the delegated validator. The commission can be set by each -validator. - -### Incentivizing Hackers - -The security of the Cosmos Hub is a function of the security of the underlying -validators and the choice of delegation by delegators. In order to encourage -the discovery and early reporting of found vulnerabilities, the Cosmos Hub -encourages hackers to publish successful exploits via a `ReportHackTx` -transaction that says, "This validator got hacked. Please send -bounty to this address". Upon such an exploit, the validator and delegators -will become inactive, `HackPunishmentRatio` (default 5%) of everyone's atoms -will get slashed, and `HackRewardRatio` (default 5%) of everyone's atoms will -get rewarded to the hacker's bounty address. The validator must recover the -remaining atoms by using their backup key. - -In order to prevent this feature from being abused to transfer unvested atoms, -the portion of vested vs unvested atoms of validators and delegators before and -after the `ReportHackTx` will remain the same, and the hacker bounty will -include some unvested atoms, if any. - -### Governance Specification - -The Cosmos Hub is operated by a distributed organization that requires a well-defined -governance mechanism in order to coordinate various changes to the blockchain, -such as the variable parameters of the system, as well as software upgrades and -constitutional amendments. - -All validators are responsible for voting on all proposals. Failing to vote on -a proposal in a timely manner will result in the validator being deactivated -automatically for a period of time called the `AbsenteeismPenaltyPeriod` -(DEFAULT 1 week). - -Delegators automatically inherit the vote of the delegated validator. This vote -may be overridden manually. Unbonded atoms get no vote. - -Each proposal requires a deposit of `MinimumProposalDeposit` tokens, which may -be a combination of one or more tokens including atoms. For each proposal, the -voters may vote to take the deposit. If more than half of the voters choose to -take the deposit (e.g. because the proposal was spam), the deposit goes to the -reserve pool, except any atoms which are burned. - -For each proposal, voters may vote with the following options: - -- Yea -- YeaWithForce -- Nay -- NayWithForce -- Abstain - -A strict majority of Yea or YeaWithForce votes (or Nay or NayWithForce votes) is -required for the proposal to be decided as passed (or decided as failed), but -1/3+ can veto the majority decision by voting "with force". When a strict -majority is vetoed, everyone gets punished by losing `VetoPenaltyFeeBlocks` -(DEFAULT 1 day's worth of blocks) worth of fees (except taxes which will not be -affected), and the party that vetoed the majority decision will be additionally -punished by losing `VetoPenaltyAtoms` (DEFAULT 0.1%) of its atoms. - -### Parameter Change Proposal - -Any of the parameters defined here can be changed with the passing of a -`ParameterChangeProposal`. - -### Bounty Proposal - -Atoms can be inflated and reserve pool funds spent with the passing of a `BountyProposal`. - -### Text Proposal - -All other proposals, such as a proposal to upgrade the protocol, will be -coordinated via the generic `TextProposal`. - -## Roadmap - -See [the Plan](https://github.com/cosmos/cosmos/blob/master/PLAN.md). - -## Related Work - -There have been many innovations in blockchain consensus and scalability in the -past couple of years. This section provides a brief survey of a select number -of important ones. - -### Consensus Systems - -#### Classic Byzantine Fault Tolerance - -Consensus in the presence of malicious participants is a problem dating back to -the early 1980s, when Leslie Lamport coined the phrase "Byzantine fault" to -refer to arbitrary process behavior that deviates from the intended behavior, -in contrast to a "crash fault", wherein a process simply crashes. Early -solutions were discovered for synchronous networks where there is an upper -bound on message latency, though practical use was limited to highly controlled -environments such as airplane controllers and datacenters synchronized via -atomic clocks. It was not until the late 90s that Practical Byzantine Fault -Tolerance (PBFT) [\[11\]][11] was introduced as an efficient partially -synchronous consensus algorithm able to tolerate up to ⅓ of processes behaving -arbitrarily. PBFT became the standard algorithm, spawning many variations, -including most recently one created by IBM as part of their contribution to -Hyperledger. - -The main benefit of Tendermint consensus over PBFT is that Tendermint has an -improved and simplified underlying structure, some of which is a result of -embracing the blockchain paradigm. Tendermint blocks must commit in order, -which obviates the complexity and communication overhead associated with PBFT's -view-changes. In Cosmos and many cryptocurrencies, there is no need to allow -for block <em>N+i</em> where <em>i >= 1</em> to commit, when block <em>N</em> -itself hasn't yet committed. If bandwidth is the reason why block <em>N</em> -hasn't committed in a Cosmos zone, then it doesn't help to use bandwidth sharing -votes for blocks <em>N+i</em>. If a network partition or offline nodes is the -reason why block <em>N</em> hasn't committed, then <em>N+i</em> won't commit -anyway. - -In addition, the batching of transactions into blocks allows for regular -Merkle-hashing of the application state, rather than periodic digests as with -PBFT's checkpointing scheme. This allows for faster provable transaction -commits for light-clients and faster inter-blockchain communication. - -Tendermint Core also includes many optimizations and features that go above and -beyond what is specified in PBFT. For example, the blocks proposed by -validators are split into parts, Merkle-ized, and gossipped in such a way that -improves broadcasting performance (see LibSwift [\[19\]][19] for inspiration). -Also, Tendermint Core doesn't make any assumption about point-to-point -connectivity, and functions for as long as the P2P network is weakly connected. - -#### BitShares delegated stake - -While not the first to deploy proof-of-stake (PoS), BitShares1.0 [\[12\]][12] -contributed considerably to research and adoption of PoS blockchains, -particularly those known as "delegated" PoS. In BitShares, stake holders elect -"witnesses", responsible for ordering and committing transactions, and -"delegates", responsible for coordinating software updates and parameter -changes. BitShares2.0 aims to achieve high performance (100k tx/s, 1s latency) -in ideal conditions, with each block signed by a single signer, and transaction -finality taking quite a bit longer than the block interval. A canonical -specification is still in development. Stakeholders can remove or replace -misbehaving witnesses on a daily basis, but there is no significant collateral -of witnesses or delegators in the likeness of Tendermint PoS that get slashed -in the case of a successful double-spend attack. - -#### Stellar - -Building on an approach pioneered by Ripple, Stellar [\[13\]][13] refined a -model of Federated Byzantine Agreement wherein the processes participating in -consensus do not constitute a fixed and globally known set. Rather, each -process node curates one or more "quorum slices", each constituting a set of -trusted processes. A "quorum" in Stellar is defined to be a set of nodes that -contain at least one quorum slice for each node in the set, such that agreement -can be reached. - -The security of the Stellar mechanism relies on the assumption that the -intersection of _any_ two quorums is non-empty, while the availability of a node -requires at least one of its quorum slices to consist entirely of correct nodes, -creating a trade-off between using large or small quorum-slices that may be -difficult to balance without imposing significant assumptions about trust. -Ultimately, nodes must somehow choose adequate quorum slices for there to be -sufficient fault-tolerance (or any "intact nodes" at all, of which much of the -results of the paper depend on), and the only provided strategy for ensuring -such a configuration is hierarchical and similar to the Border Gateway Protocol -(BGP), used by top-tier ISPs on the internet to establish global routing tables, -and by that used by browsers to manage TLS certificates; both notorious for -their insecurity. - -The criticism in the Stellar paper of the Tendermint-based proof-of-stake -systems is mitigated by the token strategy described here, wherein a new type of -token called the _atom_ is issued that represent claims to future portions of -fees and rewards. The advantage of Tendermint-based proof-of-stake, then, is its -relative simplicity, while still providing sufficient and provable security -guarantees. - -#### BitcoinNG - -BitcoinNG is a proposed improvement to Bitcoin that would allow for forms of -vertical scalability, such as increasing the block size, without the negative -economic consequences typically associated with such a change, such as the -disproportionately large impact on small miners. This improvement is achieved -by separating leader election from transaction broadcast: leaders are first -elected by proof-of-work in "micro-blocks", and then able to broadcast -transactions to be committed until a new micro-block is found. This reduces the -bandwidth requirements necessary to win the PoW race, allowing small miners to -more fairly compete, and allowing transactions to be committed more regularly by -the last miner to find a micro-block. - -#### Casper - -Casper [\[16\]][16] is a proposed proof-of-stake consensus algorithm for -Ethereum. Its prime mode of operation is "consensus-by-bet". By letting -validators iteratively bet on which block they believe will become committed -into the blockchain based on the other bets that they have seen so far, -finality can be achieved eventually. -[link](https://blog.ethereum.org/2015/12/28/understanding-serenity-part-2-casper/). -This is an active area of research by the Casper team. The challenge is in -constructing a betting mechanism that can be proven to be an evolutionarily -stable strategy. The main benefit of Casper as compared to Tendermint may be in -offering "availability over consistency" -- consensus does not require a >⅔ -quorum of voting power -- perhaps at the cost of commit speed or -implementation complexity. - -### Horizontal Scaling - -#### Interledger Protocol - -The Interledger Protocol [\[14\]][14] is not strictly a scalability solution. -It provides an ad hoc interoperation between different ledger systems through a -loosely coupled bilateral relationship network. Like the Lightning Network, -the purpose of ILP is to facilitate payments, but it specifically focuses on -payments across disparate ledger types, and extends the atomic transaction -mechanism to include not only hash-locks, but also a quorum of notaries (called -the Atomic Transport Protocol). The latter mechanism for enforcing atomicity -in inter-ledger transactions is similar to Tendermint's light-client SPV -mechanism, so an illustration of the distinction between ILP and Cosmos/IBC is -warranted, and provided below. - -1. The notaries of a connector in ILP do not support membership changes, and - do not allow for flexible weighting between notaries. On the other hand, - IBC is designed specifically for blockchains, where validators can have - different weights, and where membership can change over the course of the - blockchain. - -2. As in the Lightning Network, the receiver of payment in ILP must be online to - send a confirmation back to the sender. In a token transfer over IBC, the - validator-set of the receiver's blockchain is responsible for providing - confirmation, not the receiving user. - -3. The most striking difference is that ILP's connectors are not responsible or - keeping authoritative state about payments, whereas in Cosmos, the validators - of a hub are the authority of the state of IBC token transfers as well as the - authority of the amount of tokens held by each zone (but not the amount of - tokens held by each account within a zone). This is the fundamental innovation - that allows for secure asymmetric transfer of tokens from zone to zone; the - analog to ILP's connector in Cosmos is a persistent and maximally secure - blockchain ledger, the Cosmos Hub. - -4. The inter-ledger payments in ILP need to be backed by an exchange orderbook, - as there is no asymmetric transfer of coins from one ledger to another, only - the transfer of value or market equivalents. - -#### Sidechains - -Sidechains [\[15\]][15] are a proposed mechanism for scaling the Bitcoin -network via alternative blockchains that are "two-way pegged" to the Bitcoin -blockchain. (Two-way pegging is equivalent to bridging. In Cosmos we say -"bridging" to distinguish from market-pegging). Sidechains allow bitcoins to -effectively move from the Bitcoin blockchain to the sidechain and back, and -allow for experimentation in new features on the sidechain. As in the Cosmos -Hub, the sidechain and Bitcoin serve as light-clients of each other, using SPV -proofs to determine when coins should be transferred to the sidechain and back. -Of course, since Bitcoin uses proof-of-work, sidechains centered around Bitcoin -suffer from the many problems and risks of proof-of-work as a consensus -mechanism. Furthermore, this is a Bitcoin-maximalist solution that doesn't -natively support a variety of tokens and inter-zone network topology as Cosmos -does. That said, the core mechanism of the two-way peg is in principle the same -as that employed by the Cosmos network. - -#### Ethereum Scalability Efforts - -Ethereum is currently researching a number of different strategies to shard the -state of the Ethereum blockchain to address scalability needs. These efforts -have the goal of maintaining the abstraction layer offered by the current -Ethereum Virtual Machine across the shared state space. Multiple research -efforts are underway at this time. [\[18\]][18][\[22\]][22] - -##### Cosmos vs Ethereum 2.0 Mauve - -Cosmos and Ethereum 2.0 Mauve [\[22\]][22] have different design goals. - -- Cosmos is specifically about tokens. Mauve is about scaling general computation. -- Cosmos is not bound to the EVM, so even different VMs can interoperate. -- Cosmos lets the zone creator determine who validates the zone. -- Anyone can start a new zone in Cosmos (unless governance decides otherwise). -- The hub isolates zone failures so global token invariants are preserved. - -### General Scaling - -#### Lightning Network - -The Lightning Network is a proposed token transfer network operating at a layer -above the Bitcoin blockchain (and other public blockchains), enabling improvement of many -orders of magnitude in transaction throughput by moving the majority -of transactions outside of the consensus ledger into so-called "payment -channels". This is made possible by on-chain cryptocurrency scripts, which -enable parties to enter into bilateral stateful contracts where the state can -be updated by sharing digital signatures, and contracts can be closed by finally -publishing evidence onto the blockchain, a mechanism first popularized by -cross-chain atomic swaps. By opening payment channels with many parties, -participants in the Lightning Network can become focal points for routing the -payments of others, leading to a fully connected payment channel network, at the -cost of capital being tied up on payment channels. - -While the Lightning Network can also easily extend across multiple independent -blockchains to allow for the transfer of _value_ via an exchange market, it -cannot be used to asymmetrically transfer _tokens_ from one blockchain to -another. The main benefit of the Cosmos network described here is to enable -such direct token transfers. That said, we expect payment channels and the -Lightning Network to become widely adopted along with our token transfer -mechanism, for cost-saving and privacy reasons. - -#### Segregated Witness - -Segregated Witness is a Bitcoin improvement proposal -[link](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) that aims -to increase the per-block transaction throughput 2X or 3X, while simultaneously -making block syncing faster for new nodes. The brilliance of this solution is -in how it works within the limitations of Bitcoin's current protocol and allows -for a soft-fork upgrade (i.e. clients with older versions of the software will -continue to function after the upgrade). Tendermint, being a new protocol, has no -design restrictions, so it has a different scaling priorities. Primarily, -Tendermint uses a BFT round-robin algorithm based on cryptographic signatures -instead of mining, which trivially allows horizontal scaling through multiple -parallel blockchains, while regular, more frequent block commits allow for -vertical scaling as well. - -<hr/> - -## Appendix - -### Fork Accountability - -A well designed consensus protocol should provide some guarantees in the event that the tolerance -capacity is exceeded and the consensus fails. This is especially necessary in -economic systems, where Byzantine behaviour can have substantial financial -reward. The most important such guarantee is a form of _fork-accountability_, -where the processes that caused the consensus to fail (ie. caused clients of -the protocol to accept different values - a fork) can be identified and punished -according to the rules of the protocol, or, possibly, the legal system. When -the legal system is unreliable or excessively expensive to invoke, validators can be forced to make security -deposits in order to participate, and those deposits can be jailed, or slashed, -when malicious behaviour is detected [\[10\]][10]. - -Note this is unlike Bitcoin, where forking is a regular occurence due to -network asynchrony and the probabilistic nature of finding partial hash -collisions. Since in many cases a malicious fork is indistinguishable from a -fork due to asynchrony, Bitcoin cannot reliably implement fork-accountability, -other than the implicit opportunity cost paid by miners for mining an orphaned -block. - -### Tendermint Consensus - -We call the voting stages _PreVote_ and _PreCommit_. A vote can be for a -particular block or for _Nil_. We call a collection of >⅔ PreVotes for a single -block in the same round a _Polka_, and a collection of >⅔ PreCommits for a -single block in the same round a _Commit_. If >⅔ PreCommit for Nil in the same -round, they move to the next round. - -Note that strict determinism in the protocol incurs a weak synchrony assumption -as faulty leaders must be detected and skipped. Thus, validators wait some -amount of time, _TimeoutPropose_, before they Prevote Nil, and the value of -TimeoutPropose increases with each round. Progression through the rest of a -round is fully asynchronous, in that progress is only made once a validator hears -from >⅔ of the network. In practice, it would take an extremely strong -adversary to indefinitely thwart the weak synchrony assumption (causing the -consensus to fail to ever commit a block), and doing so can be made even more -difficult by using randomized values of TimeoutPropose on each validator. - -An additional set of constraints, or Locking Rules, ensure that the network will -eventually commit just one block at each height. Any malicious attempt to cause -more than one block to be committed at a given height can be identified. First, -a PreCommit for a block must come with justification, in the form of a Polka for -that block. If the validator has already PreCommit a block at round -<em>R*1</em>, we say they are \_locked* on that block, and the Polka used to -justify the new PreCommit at round <em>R_2</em> must come in a round -<em>R_polka</em> where <em>R_1 < R_polka <= R_2</em>. Second, validators -must Propose and/or PreVote the block they are locked on. Together, these -conditions ensure that a validator does not PreCommit without sufficient -evidence as justification, and that validators which have already PreCommit -cannot contribute to evidence to PreCommit something else. This ensures both -safety and liveness of the consensus algorithm. - -The full details of the protocol are described -[here](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm). - -### Tendermint Light Clients - -The need to sync all block headers is eliminated in Tendermint-PoS as the -existence of an alternative chain (a fork) means ≥⅓ of bonded stake can be -slashed. Of course, since slashing requires that _someone_ share evidence of a -fork, light clients should store any block-hash commits that it sees. -Additionally, light clients could periodically stay synced with changes to the -validator set, in order to avoid [long range -attacks](#preventing-long-range-attacks) (but other solutions are possible). - -In spirit similar to Ethereum, Tendermint enables applications to embed a -global Merkle root hash in each block, allowing easily verifiable state queries -for things like account balances, the value stored in a contract, or the -existence of an unspent transaction output, depending on the nature of the -application. - -### Preventing Long Range Attacks - -Assuming a sufficiently resilient collection of broadcast networks and a static -validator set, any fork in the blockchain can be detected and the deposits of -the offending validators slashed. This innovation, first suggested by Vitalik -Buterin in early 2014, solves the nothing-at-stake problem of other -proof-of-stake cryptocurrencies (see [Related Work](#related-work)). However, -since validator sets must be able to change, over a long range of time the -original validators may all become unbonded, and hence would be free to create a -new chain from the genesis block, incurring no cost as they no longer have -deposits locked up. This attack came to be known as the Long Range Attack (LRA), -in contrast to a Short Range Attack, where validators who are currently bonded -cause a fork and are hence punishable (assuming a fork-accountable BFT algorithm -like Tendermint consensus). Long Range Attacks are often thought to be a -critical blow to proof-of-stake. - -Fortunately, the LRA can be mitigated as follows. First, for a validator to -unbond (thereby recovering their collateral deposit and no longer earning fees -to participate in the consensus), the deposit must be made untransferable for an -amount of time known as the "unbonding period", which may be on the order of -weeks or months. Second, for a light client to be secure, the first time it -connects to the network it must verify a recent block-hash against a trusted -source, or preferably multiple sources. This condition is sometimes referred to -as "weak subjectivity". Finally, to remain secure, it must sync up with the -latest validator set at least as frequently as the length of the unbonding -period. This ensures that the light client knows about changes to the validator -set before a validator has its capital unbonded and thus no longer at stake, -which would allow it to deceive the client by carrying out a long range attack -by creating new blocks beginning back at a height where it was bonded (assuming -it has control of sufficiently many of the early private keys). - -Note that overcoming the LRA in this way requires an overhaul of the original -security model of proof-of-work. In PoW, it is assumed that a light client can -sync to the current height from the trusted genesis block at any time simply by -processing the proof-of-work in every block header. To overcome the LRA, -however, we require that a light client come online with some regularity to -track changes in the validator set, and that the first time they come online -they must be particularly careful to authenticate what they hear from the -network against trusted sources. Of course, this latter requirement is similar -to that of Bitcoin, where the protocol and software must also be obtained from a -trusted source. - -The above method for preventing LRA is well suited for validators and full nodes -of a Tendermint-powered blockchain because these nodes are meant to remain -connected to the network. The method is also suitable for light clients that -can be expected to sync with the network frequently. However, for light clients -that are not expected to have frequent access to the internet or the blockchain -network, yet another solution can be used to overcome the LRA. Non-validator -token holders can post their tokens as collateral with a very long unbonding -period (e.g. much longer than the unbonding period for validators) and serve -light clients with a secondary method of attesting to the validity of current -and past block-hashes. While these tokens do not count toward the security of -the blockchain's consensus, they nevertheless can provide strong guarantees for -light clients. If historical block-hash querying were supported in Ethereum, -anyone could bond their tokens in a specially designed smart contract and -provide attestation services for pay, effectively creating a market for -light-client LRA security. - -### Overcoming Forks and Censorship Attacks - -Due to the definition of a block commit, any ≥⅓ coalition of voting power can -halt the blockchain by going offline or not broadcasting their votes. Such a -coalition can also censor particular transactions by rejecting blocks that -include these transactions, though this would result in a significant proportion -of block proposals to be rejected, which would slow down the rate of block -commits of the blockchain, reducing its utility and value. The malicious -coalition might also broadcast votes in a trickle so as to grind blockchain -block commits to a near halt, or engage in any combination of these attacks. -Finally, it can cause the blockchain to fork, by double-signing or violating the -locking rules. - -If a globally active adversary were also involved, it could partition the network in -such a way that it may appear that the wrong subset of validators were -responsible for the slowdown. This is not just a limitation of Tendermint, but -rather a limitation of all consensus protocols whose network is potentially -controlled by an active adversary. - -For these types of attacks, a subset of the validators should coordinate through -external means to sign a reorg-proposal that chooses a fork (and any evidence -thereof) and the initial subset of validators with their signatures. Validators -who sign such a reorg-proposal forego their collateral on all other forks. -Clients should verify the signatures on the reorg-proposal, verify any evidence, -and make a judgement or prompt the end-user for a decision. For example, a -phone wallet app may prompt the user with a security warning, while a -refrigerator may accept any reorg-proposal signed by +½ of the original -validators by voting power. - -No non-synchronous Byzantine fault-tolerant algorithm can come to consensus when -≥⅓ of voting power are dishonest, yet a fork assumes that ≥⅓ of voting power -have already been dishonest by double-signing or lock-changing without -justification. So, signing the reorg-proposal is a coordination problem that -cannot be solved by any non-synchronous protocol (i.e. automatically, and -without making assumptions about the reliability of the underlying network). -For now, we leave the problem of reorg-proposal coordination to human -coordination via social consensus on internet media. Validators must take care -to ensure that there are no remaining network partitions prior to signing a -reorg-proposal, to avoid situations where two conflicting reorg-proposals are -signed. - -Assuming that the external coordination medium and protocol is robust, it -follows that forks are less of a concern than censorship attacks. - -In addition to forks and censorship, which require ≥⅓ Byzantine voting power, a -coalition of >⅔ voting power may commit arbitrary, invalid state. This is -characteristic of any (BFT) consensus system. Unlike double-signing, which -creates forks with easily verifiable evidence, detecting committment of an -invalid state requires non-validating peers to verify whole blocks, which -implies that they keep a local copy of the state and execute each transaction, -computing the state root independently for themselves. Once detected, the only -way to handle such a failure is via social consensus. For instance, in -situations where Bitcoin has failed, whether forking due to software bugs (as in -March 2013), or committing invalid state due to Byzantine behavior of miners (as -in July 2015), the well connected community of businesses, developers, miners, -and other organizations established a social consensus as to what manual actions -were required by participants to heal the network. Furthermore, since -validators of a Tendermint blockchain may be expected to be identifiable, -commitment of an invalid state may even be punishable by law or some external -jurisprudence, if desired. - -### ABCI Specification - -ABCI consists of 3 primary message types that get delivered from the core to the -application. The application replies with corresponding response messages. - -The `AppendTx` message is the work horse of the application. Each transaction in -the blockchain is delivered with this message. The application needs to validate -each transactions received with the AppendTx message against the current state, -application protocol, and the cryptographic credentials of the transaction. A -validated transaction then needs to update the application state — by binding a -value into a key values store, or by updating the UTXO database. - -The `CheckTx` message is similar to AppendTx, but it’s only for validating -transactions. Tendermint Core’s mempool first checks the validity of a -transaction with CheckTx, and only relays valid transactions to its peers. -Applications may check an incrementing nonce in the transaction and return an -error upon CheckTx if the nonce is old. - -The `Commit` message is used to compute a cryptographic commitment to the -current application state, to be placed into the next block header. This has -some handy properties. Inconsistencies in updating that state will now appear as -blockchain forks which catches a whole class of programming errors. This also -simplifies the development of secure lightweight clients, as Merkle-hash proofs -can be verified by checking against the block-hash, and the block-hash is signed -by a quorum of validators (by voting power). - -Additional ABCI messages allow the application to keep track of and change the -validator set, and for the application to receive the block information, such as -the height and the commit votes. - -ABCI requests/responses are simple Protobuf messages. Check out the [schema -file](https://github.com/tendermint/abci/blob/master/types/types.proto). - -##### AppendTx - -- **Arguments**: - - `Data ([]byte)`: The request transaction bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: Result bytes, if any - - `Log (string)`: Debug or error message -- **Usage**:<br/> - Append and run a transaction. If the transaction is valid, returns - CodeType.OK - -##### CheckTx - -- **Arguments**: - - `Data ([]byte)`: The request transaction bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: Result bytes, if any - - `Log (string)`: Debug or error message -- **Usage**:<br/> - Validate a transaction. This message should not mutate the state. - Transactions are first run through CheckTx before broadcast to peers in the - mempool layer. - You can make CheckTx semi-stateful and clear the state upon `Commit` or - `BeginBlock`, - to allow for dependent sequences of transactions in the same block. - -##### Commit - -- **Returns**: - - `Data ([]byte)`: The Merkle root hash - - `Log (string)`: Debug or error message -- **Usage**:<br/> - Return a Merkle root hash of the application state. - -##### Query - -- **Arguments**: - - `Data ([]byte)`: The query request bytes -- **Returns**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: The query response bytes - - `Log (string)`: Debug or error message - -##### Flush - -- **Usage**:<br/> - Flush the response queue. Applications that implement `types.Application` - need not implement this message -- it's handled by the project. - -##### Info - -- **Returns**: - - `Data ([]byte)`: The info bytes -- **Usage**:<br/> - Return information about the application state. Application specific. - -##### SetOption - -- **Arguments**: - - `Key (string)`: Key to set - - `Value (string)`: Value to set for key -- **Returns**: - - `Log (string)`: Debug or error message -- **Usage**:<br/> - Set application options. E.g. Key="mode", Value="mempool" for a mempool - connection, or Key="mode", Value="consensus" for a consensus connection. - Other options are application specific. - -##### InitChain - -- **Arguments**: - - `Validators ([]Validator)`: Initial genesis-validators -- **Usage**:<br/> - Called once upon genesis - -##### BeginBlock - -- **Arguments**: - - `Height (uint64)`: The block height that is starting -- **Usage**:<br/> - Signals the beginning of a new block. Called prior to any AppendTxs. - -##### EndBlock - -- **Arguments**: - - `Height (uint64)`: The block height that ended -- **Returns**: - - `Validators ([]Validator)`: Changed validators with new voting powers (0 - to remove) -- **Usage**:<br/> - Signals the end of a block. Called prior to each Commit after all - transactions - -See [the ABCI repository](https://github.com/tendermint/abci#message-types) for more details. - -### IBC Packet Delivery Acknowledgement - -There are several reasons why a sender may want the acknowledgement of delivery -of a packet by the receiving chain. For example, the sender may not know the -status of the destination chain, if it is expected to be faulty. Or, the sender -may want to impose a timeout on the packet (with the `MaxHeight` packet field), -while any destination chain may suffer from a denial-of-service attack with a -sudden spike in the number of incoming packets. - -In these cases, the sender can require delivery acknowledgement by setting the -initial packet status to `AckPending`. Then, it is the receiving chain's -responsibility to confirm delivery by including an abbreviated `IBCPacket` in the -app Merkle hash. - -![Figure of Zone1, Zone2, and Hub IBC with -acknowledgement](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack.png) - -First, an `IBCBlockCommit` and `IBCPacketTx` are posted on "Hub" that proves -the existence of an `IBCPacket` on "Zone1". Say that `IBCPacketTx` has the -following value: - -- `FromChainID`: "Zone1" -- `FromBlockHeight`: 100 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 (say) - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 (say "Hub" is currently at height 300) - - `Payload`: <The bytes of a "coin" payload> - -Next, an `IBCBlockCommit` and `IBCPacketTx` are posted on "Zone2" that proves -the existence of an `IBCPacket` on "Hub". Say that `IBCPacketTx` has the -following value: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 300 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckPending` - - `Type`: "coin" - - `MaxHeight`: 350 - - `Payload`: <The same bytes of a "coin" payload> - -Next, "Zone2" must include in its app-hash an abbreviated packet that shows the -new status of `AckSent`. An `IBCBlockCommit` and `IBCPacketTx` are posted back -on "Hub" that proves the existence of an abbreviated `IBCPacket` on -"Zone2". Say that `IBCPacketTx` has the following value: - -- `FromChainID`: "Zone2" -- `FromBlockHeight`: 400 (say) -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckSent` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <The hash bytes of the same "coin" payload> - -Finally, "Hub" must update the status of the packet from `AckPending` to -`AckReceived`. Evidence of this new finalized status should go back to -"Zone2". Say that `IBCPacketTx` has the following value: - -- `FromChainID`: "Hub" -- `FromBlockHeight`: 301 -- `Packet`: an `IBCPacket`: - - `Header`: an `IBCPacketHeader`: - - `SrcChainID`: "Zone1" - - `DstChainID`: "Zone2" - - `Number`: 200 - - `Status`: `AckReceived` - - `Type`: "coin" - - `MaxHeight`: 350 - - `PayloadHash`: <The hash bytes of the same "coin" payload> - -Meanwhile, "Zone1" may optimistically assume successful delivery of a "coin" -packet unless evidence to the contrary is proven on "Hub". In the example -above, if "Hub" had not received an `AckSent` status from "Zone2" by block -350, it would have set the status automatically to `Timeout`. This evidence of -a timeout can get posted back on "Zone1", and any tokens can be returned. - -![Figure of Zone1, Zone2, and Hub IBC with acknowledgement and -timeout](https://raw.githubusercontent.com/gnuclear/atom-whitepaper/master/msc/ibc_with_ack_timeout.png) - -### Merkle Tree & Proof Specification - -There are two types of Merkle trees supported in the Tendermint/Cosmos -ecosystem: The Simple Tree, and the IAVL+ Tree. - -#### Simple Tree - -The Simple Tree is a Merkle tree for a static list of elements. If the number -of items is not a power of two, some leaves will be at different levels. Simple -Tree tries to keep both sides of the tree the same height, but the left may be -one greater. This Merkle tree is used to Merkle-ize the transactions of a -block, and the top level elements of the application state root. - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - - A SimpleTree with 7 elements - -#### IAVL+ Tree - -The purpose of the IAVL+ data structure is to provide persistent storage for -key-value pairs in the application state such that a deterministic Merkle root -hash can be computed efficiently. The tree is balanced using a variant of the -[AVL algorithm](https://en.wikipedia.org/wiki/AVL_tree), and all operations are -O(log(n)). - -In an AVL tree, the heights of the two child subtrees of any node differ by at -most one. Whenever this condition is violated upon an update, the tree is -rebalanced by creating O(log(n)) new nodes that point to unmodified nodes of the -old tree. In the original AVL algorithm, inner nodes can also hold key-value -pairs. The AVL+ algorithm (note the plus) modifies the AVL algorithm to keep -all values on leaf nodes, while only using branch-nodes to store keys. This -simplifies the algorithm while keeping the merkle hash trail short. - -The AVL+ Tree is analogous to Ethereum's [Patricia -tries](https://en.wikipedia.org/wiki/Radix_tree). There are tradeoffs. Keys do -not need to be hashed prior to insertion in IAVL+ trees, so this provides faster -ordered iteration in the key space which may benefit some applications. The -logic is simpler to implement, requiring only two types of nodes -- inner nodes -and leaf nodes. The Merkle proof is on average shorter, being a balanced binary -tree. On the other hand, the Merkle root of an IAVL+ tree depends on the order -of updates. - -We will support additional efficient Merkle trees, such as Ethereum's Patricia -Trie when the binary variant becomes available. - -### Transaction Types - -In the canonical implementation, transactions are streamed to the Cosmos hub -application via the ABCI interface. - -The Cosmos Hub will accept a number of primary transaction types, including -`SendTx`, `BondTx`, `UnbondTx`, `ReportHackTx`, `SlashTx`, `BurnAtomTx`, -`ProposalCreateTx`, and `ProposalVoteTx`, which are fairly self-explanatory and -will be documented in a future revision of this paper. Here we document the two -primary transaction types for IBC: `IBCBlockCommitTx` and `IBCPacketTx`. - -#### IBCBlockCommitTx - -An `IBCBlockCommitTx` transaction is composed of: - -- `ChainID (string)`: The ID of the blockchain -- `BlockHash ([]byte)`: The block-hash bytes, the Merkle root which includes the - app-hash -- `BlockPartsHeader (PartSetHeader)`: The block part-set header bytes, only - needed to verify vote signatures -- `BlockHeight (int)`: The height of the commit -- `BlockRound (int)`: The round of the commit -- `Commit ([]Vote)`: The >⅔ Tendermint `Precommit` votes that comprise a block - commit -- `ValidatorsHash ([]byte)`: A Merkle-tree root hash of the new validator set -- `ValidatorsHashProof (SimpleProof)`: A SimpleTree Merkle-proof for proving the - `ValidatorsHash` against the `BlockHash` -- `AppHash ([]byte)`: A IAVLTree Merkle-tree root hash of the application state -- `AppHashProof (SimpleProof)`: A SimpleTree Merkle-proof for proving the - `AppHash` against the `BlockHash` - -#### IBCPacketTx - -An `IBCPacket` is composed of: - -- `Header (IBCPacketHeader)`: The packet header -- `Payload ([]byte)`: The bytes of the packet payload. _Optional_ -- `PayloadHash ([]byte)`: The hash for the bytes of the packet. _Optional_ - -Either one of `Payload` or `PayloadHash` must be present. The hash of an -`IBCPacket` is a simple Merkle root of the two items, `Header` and `Payload`. -An `IBCPacket` without the full payload is called an _abbreviated packet_. - -An `IBCPacketHeader` is composed of: - -- `SrcChainID (string)`: The source blockchain ID -- `DstChainID (string)`: The destination blockchain ID -- `Number (int)`: A unique number for all packets -- `Status (enum)`: Can be one of `AckPending`, `AckSent`, `AckReceived`, - `NoAck`, or `Timeout` -- `Type (string)`: The types are application-dependent. Cosmos reserves the - "coin" packet type -- `MaxHeight (int)`: If status is not `NoAckWanted` or `AckReceived` by this - height, status becomes `Timeout`. _Optional_ - -An `IBCPacketTx` transaction is composed of: - -- `FromChainID (string)`: The ID of the blockchain which is providing this - packet; not necessarily the source -- `FromBlockHeight (int)`: The blockchain height in which the following packet - is included (Merkle-ized) in the block-hash of the source chain -- `Packet (IBCPacket)`: A packet of data, whose status may be one of - `AckPending`, `AckSent`, `AckReceived`, `NoAck`, or `Timeout` -- `PacketProof (IAVLProof)`: A IAVLTree Merkle-proof for proving the packet's - hash against the `AppHash` of the source chain at given height - -The sequence for sending a packet from "Zone1" to "Zone2" through the -"Hub" is depicted in {Figure X}. First, an `IBCPacketTx` proves to -"Hub" that the packet is included in the app-state of "Zone1". Then, -another `IBCPacketTx` proves to "Zone2" that the packet is included in the -app-state of "Hub". During this procedure, the `IBCPacket` fields are -identical: the `SrcChainID` is always "Zone1", and the `DstChainID` is always -"Zone2". - -The `PacketProof` must have the correct Merkle-proof path, as follows: - - IBC/<SrcChainID>/<DstChainID>/<Number> - -When "Zone1" wants to send a packet to "Zone2" through "Hub", the -`IBCPacket` data are identical whether the packet is Merkle-ized on "Zone1", -the "Hub", or "Zone2". The only mutable field is `Status` for tracking -delivery. - -## Acknowledgements - -We thank our friends and peers for assistance in conceptualizing, reviewing, and -providing support for our work with Tendermint and Cosmos. - -- [Zaki Manian](https://github.com/zmanian) of - [SkuChain](http://www.skuchain.com/) provided much help in formatting and - wording, especially under the ABCI section -- [Jehan Tremback](https://github.com/jtremback) of Althea and Dustin Byington - for helping with initial iterations -- [Andrew Miller](https://soc1024.com/) of [Honey - Badger](https://eprint.iacr.org/2016/199) for feedback on consensus -- [Greg Slepak](https://fixingtao.com/) for feedback on consensus and wording -- Also thanks to [Bill Gleim](https://github.com/gleim) and [Seunghwan - Han](http://www.seunghwanhan.com) for various contributions. -- **Your name and organization here for your contribution** - -## Citations - -- [1] Bitcoin: <https://bitcoin.org/bitcoin.pdf> -- [2] ZeroCash: <http://zerocash-project.org/paper> -- [3] Ethereum: <https://github.com/ethereum/wiki/wiki/White-Paper> -- [4] TheDAO: <https://download.slock.it/public/DAO/WhitePaper.pdf> -- [5] Segregated Witness: <https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki> -- [6] BitcoinNG: <https://arxiv.org/pdf/1510.02037v2.pdf> -- [7] Lightning Network: <https://lightning.network/lightning-network-paper-DRAFT-0.5.pdf> -- [8] Tendermint: <https://github.com/tendermint/tendermint/wiki> -- [9] FLP Impossibility: <https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf> -- [10] Slasher: <https://blog.ethereum.org/2014/01/15/slasher-a-punitive-proof-of-stake-algorithm/> -- [11] PBFT: <http://pmg.csail.mit.edu/papers/osdi99.pdf> -- [12] BitShares: <https://bitshares.org/technology/delegated-proof-of-stake-consensus/> -- [13] Stellar: <https://www.stellar.org/papers/stellar-consensus-protocol.pdf> -- [14] Interledger: <https://interledger.org/rfcs/0001-interledger-architecture/> -- [15] Sidechains: <https://blockstream.com/sidechains.pdf> -- [16] Casper: <https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/> -- [17] ABCI: <https://github.com/tendermint/abci> -- [18] Ethereum Sharding: <https://github.com/ethereum/EIPs/issues/53> -- [19] LibSwift: <http://www.ds.ewi.tudelft.nl/fileadmin/pds/papers/PerformanceAnalysisOfLibswift.pdf> -- [20] DLS: <http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf> -- [21] Thin Client Security: <https://en.bitcoin.it/wiki/Thin_Client_Security> -- [22] Ethereum 2.0 Mauve Paper: <https://cdn.hackaday.io/files/10879465447136/Mauve%20Paper%20Vitalik.pdf> - -#### Unsorted links - -- <https://www.docdroid.net/ec7xGzs/314477721-ethereum-platform-review-opportunities-and-challenges-for-private-and-consortium-blockchains.pdf> diff --git a/docs/sdk/cosmos-sdk-cli.md b/docs/sdk/cosmos-sdk-cli.md deleted file mode 100644 index 615d722522b9..000000000000 --- a/docs/sdk/cosmos-sdk-cli.md +++ /dev/null @@ -1,34 +0,0 @@ -# cosmos-sdk-cli -Create a new blockchain project based on cosmos-sdk with a single command. - ---- - -# Installation - -```shell -$ go get github.com/cosmos/cosmos-sdk -$ cd $GOPATH/src/github.com/cosmos/cosmos-sdk -$ make install_cosmos-sdk-cli -``` - -This will install a binary cosmos-sdk-cli - -# Creating a new project - -**$cosmos-sdk-cli init** _Your-Project-Name_ - -This will initialize a project, the dependencies, directory structures with the specified project name. - -### Example: -```shell -$ cosmos-sdk-cli init testzone -p github.com/your_user_name/testzone -``` -`-p [remote-project-path]`. If this is not provided, it creates testzone under $GOPATH/src/ - - -```shell -$ cd $GOPATH/src/github.com/your_user_name/testzone -$ make -``` -This will create two binaries(testzonecli and testzoned) under bin folder. testzoned is the full node of the application which you can run, and testzonecli is your light client. - diff --git a/docs/sdk/modules.md b/docs/sdk/modules.md deleted file mode 100644 index 7df8fb2bb0bb..000000000000 --- a/docs/sdk/modules.md +++ /dev/null @@ -1,19 +0,0 @@ -# Modules - -::: tip Note -🚧 We are actively working on documentation for SDK modules. -::: - -The Cosmos SDK has all the necessary pre-built modules to add functionality on top of a `BaseApp`, which is the template to build a blockchain dApp in Cosmos. In this context, a `module` is a fundamental unit in the Cosmos SDK. - -Each module is an extension of the `BaseApp`'s functionalities that defines transactions, handles application state and manages the state transition logic. Each module also contains handlers for messages and transactions, queriers for handling query requests, as well as REST and CLI for secure user interactions. - -Some of the most important modules in the SDK are: - -- `Auth`: Defines a standard account structure (`BaseAccount`) and how transaction signers are authenticated. -- `Bank`: Defines how coins or tokens (i.e cryptocurrencies) are transferred. -- `Fees`: -- `Governance`: Governance related implementation including proposals and voting. -- `IBC`: Defines the intereoperability of blockchain zones according to the specifications of the [IBC Protocol](https://cosmos.network/whitepaper#inter-blockchain-communication-ibc). -- `Slashing`: -- `Staking`: Proof of Stake related implementation including bonding and delegation transactions, inflation, fees, unbonding, etc. diff --git a/docs/sdk/overview.md b/docs/sdk/overview.md deleted file mode 100644 index 70e826c60a14..000000000000 --- a/docs/sdk/overview.md +++ /dev/null @@ -1,205 +0,0 @@ -# Cosmos SDK Overview - -The [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk) is a framework for building multi-asset Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as Proof-Of-Authority (PoA) blockchains. - -The goal of the Cosmos-SDK is to allow developers to easily create custom interoperable blockchain applications within the Cosmos Network without having to recreate common blockchain functionality, thus removing the complexity of building a Tendermint ABCI application. We envision the SDK as the npm-like framework to build secure blockchain applications on top of Tendermint. - -In terms of its design, the SDK optimizes flexibility and security. The framework is designed around a modular execution stack which allows applications to mix and match elements as desired. In addition, all modules are sandboxed for greater application security. - -It is based on two major principles: - -- **Composability:** Anyone can create a module for the Cosmos-SDK and integrating the already-built modules is as simple as importing them into your blockchain application. - -- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework and that we assume that some of those modules may be malicious, we designed the SDK using object-capabilities (ocaps) based principles. 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. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each 3rd party module. For a deeper look at capabilities, you can read this [article](http://habitatchronicles.com/2017/05/what-are-capabilities/). - -For an introduction to object-capabilities, see this [article](http://habitatchronicles.com/2017/05/what-are-capabilities/). - -## Languages - -The Cosmos-SDK is currently written in [Golang](https://golang.org/), though the -framework could be implemented similarly in other languages. -Contact us for information about funding an implementation in another language. - -## Directory Structure - -The SDK is laid out in the following directories: - -- `baseapp`: Defines the template for a basic [ABCI](https://cosmos.network/whitepaper#abci) application so that your Cosmos-SDK application can communicate with the underlying Tendermint node. -- `client`: CLI and REST server tooling for interacting with SDK application. -- `examples`: Examples of how to build working standalone applications. -- `server`: The full node server for running an SDK application on top of - Tendermint. -- `store`: The database of the SDK - a Merkle multistore supporting multiple types of underling Merkle key-value stores. -- `types`: Common types in SDK applications. -- `x`: Extensions to the core, where all messages and handlers are defined. - -## Object-Capability Model - -When thinking about security, it's good to start with a specific threat -model. Our threat model is the following: - -> 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. - -The Cosmos-SDK is designed to address this threat by being the -foundation of an object capability system. - -> The structural properties of object capability systems favor -> modularity in code design and ensure reliable encapsulation in -> code implementation. -> -> These structural properties facilitate the analysis of some -> security properties of an object-capability program or operating -> system. Some of these — in particular, information flow properties -> — can be analyzed at the level of object references and -> connectivity, independent of any knowledge or analysis of the code -> that determines the behavior of the objects. -> -> As a consequence, these security properties can be established -> and maintained in the presence of new objects that contain unknown -> and possibly malicious code. -> -> These structural properties stem from the two rules governing -> access to existing objects: -> -> 1. An object A can send a message to B only if object A holds a -> reference to B. -> 2. An object A can obtain a reference to C only -> if object A receives a message containing a reference to C. As a -> consequence of these two rules, an object can obtain a reference -> to another object only through a preexisting chain of references. -> In short, "Only connectivity begets connectivity." - -See the [wikipedia -article](https://en.wikipedia.org/wiki/Object-capability_model) on the Object Capability Model for more -information. - -Strictly speaking, Golang does not implement object capabilities -completely, because of several issues: - -- pervasive ability to import primitive modules (e.g. "unsafe", "os") -- pervasive ability to override module vars <https://github.com/golang/go/issues/23161> -- data-race vulnerability where 2+ goroutines can create illegal interface values - -The first is easy to catch by auditing imports and using a proper -dependency version control system like Dep. The second and third are -unfortunate but it can be audited with some cost. - -Perhaps [Go2 will implement the object capability -model](https://github.com/golang/go/issues/23157). - -### What does it look like? - -Only reveal what is necessary to get the work done. - -For example, the following code snippet violates the object capabilities -principle: - -```go -type AppAccount struct {...} -var account := &AppAccount{ - Address: pub.Address(), - Coins: sdk.Coins{{"ATM", 100}}, -} -var sumValue := externalModule.ComputeSumValue(account) -``` - -The method `ComputeSumValue` implies a pure function, yet the implied -capability of accepting a pointer value is the capability to modify that -value. The preferred method signature should take a copy instead. - -```go -var sumValue := externalModule.ComputeSumValue(*account) -``` - -In the Cosmos SDK, you can see the application of this principle in the -basecoin examples folder. - -```go -// File: cosmos-sdk/examples/basecoin/app/init_handlers.go -package app - -import ( - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/sketchy" -) - -func (app *BasecoinApp) initRouterHandlers() { - - // All handlers must be added here. - // The order matters. - app.router.AddRoute("bank", bank.NewHandler(app.accountKeeper)) - app.router.AddRoute("sketchy", sketchy.NewHandler()) -} -``` - -In the Basecoin example, the sketchy handler isn't provided an account -mapper, which does provide the bank handler with the capability (in -conjunction with the context of a transaction run). - -## Application Architecture - -The SDK has multiple levels of "application": the ABCI app, the BaseApp, the BasecoinApp, and now your App. - -### ABCI App - -The basic ABCI interface allowing Tendermint to drive the applications state machine with transaction blocks. - -### BaseApp - -Implements an ABCI App using a MultiStore for persistence and a Router to handle transactions. -The goal is to provide a secure interface between the store and the extensible state machine -while defining as little about that state machine as possible (staying true to the ABCI). - -BaseApp requires stores to be mounted via capabilities keys - handlers can only access -stores they're given the key for. The BaseApp ensures all stores are properly loaded, cached, and committed. -One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the most recent state. - -BaseApp distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`. -The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees, -e.g. things that apply to all transaction from all modules), the later is the full state transition function. -During CheckTx the state transition function is only applied to the checkTxState and should return -before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated -gas cost. - -During DeliverTx the state transition function is applied to the blockchain state and the transactions -need to be fully executed. - -BaseApp is responsible for managing the context passed into handlers - it makes the block header available and provides the right stores for CheckTx and DeliverTx. BaseApp is completely agnostic to serialization formats. - -### Basecoin - -Basecoin is the first complete application in the stack. Complete applications require extensions to the core modules of the SDK to actually implement handler functionality. - -The native extensions of the SDK, useful for building Cosmos Zones, live under `x`. -Basecoin implements a `BaseApp` state machine using the `x/auth` and `x/bank` extensions, -which define how transaction signers are authenticated and how coins are transferred. -It should also use `x/ibc` and probably a simple staking extension. - -Basecoin and the native `x` extensions use go-amino for all serialization needs, -including for transactions and accounts. - -### Your Cosmos App - -Your Cosmos App is a fork of Basecoin - copy the `examples/basecoin` directory and modify it to your needs. -You may want to: - -- add fields to accounts -- copy and modify handlers -- add new handlers for new transaction types -- add new stores for better isolation across handlers - -The Cosmos Hub takes Basecoin and adds more stores and extensions to handle additional -transaction types and logic, like the advanced staking logic and the governance process. - -## Ethermint - -Ethermint is a new implementation of `BaseApp` that does not depend on Basecoin. -Instead of `cosmos-sdk/x/` it has its own `ethermint/x` based on `go-ethereum`. - -Ethermint uses a Patricia store for its accounts, and an IAVL store for IBC. -It has `x/ante`, which is quite similar to Basecoin's but uses RLP instead of go-amino. -Instead of `x/bank`, it has `x/eth`, which defines the single Ethereum transaction type -and all the semantics of the Ethereum state machine. - -Within `x/eth`, transactions sent to particular addresses can be handled in unique ways, -for instance to handle IBC and staking. diff --git a/docs/spec/README.md b/docs/spec/README.md index 49ea67b7a212..047b1ca98ecf 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -1,28 +1,31 @@ -# Cosmos Hub Spec +# Specifications -This directory contains specifications for the state transition machine of the -Cosmos Hub. +This directory contains specifications for the modules of the Cosmos SDK as well as Interchain Standards (ICS) and other specifications. -The Cosmos Hub holds all of its state in a Merkle store. Updates to +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. -While the first implementation of the Cosmos Hub is built using the Cosmos-SDK, -these specifications aim to be independent of any implementation details. That -said, they provide a detailed resource for understanding the Cosmos-SDK. - -- [Store](store) - The core Merkle store that holds the state. -- [Auth](auth) - The structure and authentication of accounts and transactions. -- [Bank](bank) - Sending tokens. -- [Governance](governance) - Proposals and voting. -- [Staking](staking) - Proof-of-stake bonding, delegation, etc. -- [Slashing](slashing) - Validator punishment mechanisms. -- [Distribution](distribution) - Fee distribution, and atom provision distribution -- [Inflation](inflation) - Atom provision creation -- [IBC](ibc) - Inter-Blockchain Communication (IBC) protocol. -- [Other](other) - Other components of the Cosmos Hub, including the reserve - pool, All in Bits vesting, etc. +### SDK specifications: + +- [Store](./store) - The core Merkle store that holds the state. +- [Bech32](./other/bech32.md) - Address format for Cosmos SDK applications. + +### Modules specifications: + +- [Auth](./auth) - The structure and authentication of accounts and transactions. +- [Bank](./bank) - Sending tokens. +- [Governance](./governance) - Proposals and voting. +- [Staking](./staking) - Proof-of-stake bonding, delegation, etc. +- [Slashing](./slashing) - Validator punishment mechanisms. +- [Distribution](./distribution) - Fee distribution, and staking token provision distribution . +- [Inflation](./inflation) - Staking token provision creation +- [IBC](./ibc) - Inter-Blockchain Communication (IBC) protocol. + +### Interchain standards + +- [ICS30](./ics/ics-030-signed-messages.md) - Signed messages standard. +- For details on the underlying blockchain and p2p protocols, see the [Tendermint specification](https://github.com/tendermint/tendermint/tree/develop/docs/spec). - diff --git a/docs/ics/ics-030-signed-messages.md b/docs/spec/ics/ics-030-signed-messages.md similarity index 100% rename from docs/ics/ics-030-signed-messages.md rename to docs/spec/ics/ics-030-signed-messages.md diff --git a/docs/spec-proposals/f1-fee-distribution/f1_fee_distr.pdf b/docs/spec/spec-proposals/f1-fee-distribution/f1_fee_distr.pdf similarity index 100% rename from docs/spec-proposals/f1-fee-distribution/f1_fee_distr.pdf rename to docs/spec/spec-proposals/f1-fee-distribution/f1_fee_distr.pdf diff --git a/docs/spec-proposals/f1-fee-distribution/f1_fee_distr.tex b/docs/spec/spec-proposals/f1-fee-distribution/f1_fee_distr.tex similarity index 100% rename from docs/spec-proposals/f1-fee-distribution/f1_fee_distr.tex rename to docs/spec/spec-proposals/f1-fee-distribution/f1_fee_distr.tex diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index fc25f5ec4fbf..31780f68e74d 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -528,7 +528,7 @@ func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command { return cmd } -// GetCmdQueryDeposits implements the command to query for proposal deposits. +// GetCmdQueryTally implements the command to query for proposal tally result. func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "tally",