Please note, that the only officially supported platform now is Linux. It's recommended to develop and deploy the App on Ubuntu 24.04. It also works on other versions of Ubuntu(20.04, 22.04)
-
Install Go as described at https://golang.org/doc/install
-
Ensure that the following line has been appended to
/etc/profile:export PATH=$PATH:/usr/local/go/bin
-
Ensure that the following line has been appended to
~/.profile:export PATH=$PATH:~/go/bin
-
-
Install Docker as described at https://docs.docker.com/engine/install/ubuntu/
-
In
Installation methodssection followInstall using the repositorymethod -
Check whether your user of Ubuntu has been added to
dockergroup using the following command:getent group docker | awk -F: '{print $4}'
- If it has not been added, add it using
Manage Docker as a non-root usersection from https://docs.docker.com/engine/install/linux-postinstall/
- If it has not been added, add it using
-
-
Install Docker Compose as described at https://docs.docker.com/compose/install/
-
Building
make build make install
-
Run unit tests
make test -
Run integration tests.
The integration tests are run against a local pool of nodes in Docker. REST integration tests need to have a backend running (CLI in REST mode).
The following script will start all necessary things and run all the tests:
./integration_tests/run-all.sh
If you want to run a particular group of tests (cli, light, rest, deploy, upgrade), you can
./integration_tests/run-all.sh cli ./integration_tests/run-all.sh light ./integration_tests/run-all.sh rest ./integration_tests/run-all.sh upgrade ./integration_tests/run-all.sh cli,light
If you want to run a particular test you may:
./integration_tests/start-pool.sh bash <path-to-shell-script> # to run a cli test # OR go test <path-to-go-test-file> # to run REST or gRPC go test
-
Run deployment test
The deployment test verifies deployment steps described in docs/running-node.md.
./integration_tests/deploy/test_deploy.sh
The easiest way to run a local pool is to start it in Docker.
Validator nodes only (no Observers):
make install
make localnet_init
make localnet_startValidator and Observer nodes:
make install
DCL_OBSERVERS=1 make localnet_init
make localnet_startThis will start a local pool of 4 validator nodes in Docker. The nodes will expose their RPC endpoints on ports 26657, 26659, 26661, 26663 correspondingly.
Stopping the network:
make localnet_stopThen you can start the network again with the existing data using make localnet_start
If you need to start a new clean network then run make localnet_rebuild prior to executing make localnet_start.
It will remove .dcl directories from your user home directory (~), remove .localnet directory from the root directory of the cloned project,
and initialize a new network data using make localnet_init.
Start a local pool as described above, and then just execute
dcldHave a look at How To and transactions for instructions how to configure and use the CLI.
Start a local pool as described above.
Every node exposes a REST API at http://<node-host>:1317 (see https://docs.cosmos.network/sdk/v0.47/learn/advanced/grpc_rest).
Have a look at transactions for a full list of REST endpoints.
Please take into account the following when sending a PR:
-
Make sure the new functionality has unit tests added
-
Make sure the new functionality has integration tests added
-
There is CI based on GitHub Actions that will do the following for every Pull Request:
- make sure the app can be built
- run go linter
- run unit tests
- run integration tests
- Use ignite v0.27.1 command to scaffold the module. Consider using a docker container built from the provided Dockerfile to have a predictable version of ignite. See README.md.
-
Note:
Have a look at the scripts and commands used for generation of existing modules, messages and CRUD operations and do it in a similar way (for example PKI module commands).
- On previous scaffolding of modules
starportcli used instead ofignite. While generating new module, command structure will the same except it must start withignite. - After execution of command
ignite scaffold ...generated.protofiles will be added intoproto/distributedcoplianceledger/{module}/{proto}. So make sure to put contents of generated proto files into related folders insideproto/zigbeealliance/..folder.
- On previous scaffolding of modules
- If a new transaction with a new data in state (key-value) and new queries needs to be created, then both message and CRUD commands need to be executed.
- If just a message to update existing state values need to be created, then a message command is enough.
- Adjust the generated code
-
increment the return value of
AppModule.ConsensusVersionmethod inx/<module>/module.go -
correct REST endpoints:
/dclinstead of/zigbee-alliance/distributedcomplianceledgerinproto/<module>/query.protoand in entries related to queries of the new module indocs/static/openapi.yml -
add message validation as annotations (
validatetags) inproto/<module>/tx.proto -
add
(cosmos_proto.scalar) = "cosmos.AddressString"annotation for all fields with address/account type (such assignerorowner). -
fix types if needed in
proto/<module>/<entity>.protofiles- Note1:
unit64will be returned as string if the output is a JSON format. So, it's better to useuint64only when it's reallyuint64. - Note2: for
uint16type: useint32during ignite scaffolding, and add custom validation (annotations above) to check the lower and upper bounds. - Note3: for
uint32type: useint32during ignite scaffolding, then replace it byuint32in .proto files, re-generate the code and fix compilation errors.
- Note1:
-
build proto (for example
ignite chain build). Fix compilation errors if any. -
generate openapi docs from proto using (
scripts/dcl-swagger-gen.sh). It's recommended to run from container built from Dockerfile -
regenerate the TypeScript client via
make ts-client-gen(see Regenerate the TypeScript Client). -
Note1: colons (
:) are part of subject-id in PKI module, but colons are not allowed in gRPC REST URLs by default.allow_colon_final_segments=trueshould be used as a workaround. So, make sure thatruntime.AssumeColonVerbOpt(false)in/x/pki/types/query.pb.gw.go. It's usually sufficient to revert the generated changes in/x/pki/types/query.pb.gw.go. It may be easier just to revert changes in all*.pb.gofiles not affected by your changes in.proto -
Note3:
ignite chain buildneeds to be called only if you made manual changes in.protofiles. There is no need to callignite chain buildagain once all errors and adjustments above are done. It's sufficient just to build the project via usual ways (such asmake build)
-
- Add static validation for new messages:
- Call
validator.Validate(msg)inValidateBasicmethods for all generated messages - Add additional checks to
ValidateBasicthat do not depend on the state (key-value) and order of transactions
- Call
- Implement business logic in
msg_server_xxx.go - Improve
NotFounderror processing:- replace
status.Error(codes.InvalidArgument, "not found")tostatus.Error(codes.NotFound, "not found")in every generatedgrpc_query_xxx.goto return 404 error in REST.
- replace
- Support state proof for single value queries in CLI:
- use
cli.QueryWithProofinstead of cosmos queries that doesn't support state proofs - add proper handling for list queries and write requests when used with a light client proxy
(see
IsWriteInsteadReadRpcErrorandIsKeyNotFoundRpcError)
- use
- Add unit tests (see other modules for reference)
- Add CLI-based integration tests to
integration_tests/cli/<module>(see other modules for reference) - Add gRPC/REST-based integration tests to
integration_tests/grpc_rest/<module>(see other modules for reference)
-
Use ignite command to scaffold the module. Consider using the provided Dockerfile to have a predictable version of ignite. See README.md.
-
Never change
.pbfiles manually. Do the changes in.protofiles. -
Every time
.protofiles change, re-generate the code (for exampleignite chain build) and fix compilation errors if any. -
Update openapi docs from proto using (
scripts/dcl-swagger-gen.sh). It's recommended to run from container built from Dockerfile. -
Regenerate the TypeScript client via
make ts-client-gen(see Regenerate the TypeScript Client). -
Note1: colons (
:) are part of subject-id in PKI module, but colons are not allowed in gRPC REST URLs by default.allow_colon_final_segments=trueshould be used as a workaround. So, make sure thatruntime.AssumeColonVerbOpt(false)in/x/pki/types/query.pb.gw.go. It's usually sufficient to revert the generated changes in/x/pki/types/query.pb.gw.go. -
Note2: move
compliance_info.pb.goandcompliance_history_item.pb.gototypes/complianceand adjust the import in other places accordingly. It may be easier just to revert changes in all*.pb.gofiles not affected by your changes in.proto -
Note3:
ignite chain buildneeds to be called only if you made manual changes in.protofiles. There is no need to callignite chain buildagain once all errors and adjustments above are done. It's sufficient just to build the project via usual ways (such asmake build)
The TypeScript client under ts-client/ is generated from the .proto files via ignite generate ts-client.
After regeneration, the RFC 3986 query-encoding patch must be re-applied so base64 pagination keys
(which contain +, /, =) survive transit — otherwise the cosmos-sdk gRPC-gateway decodes + as
space and rejects next_key follow-up requests with illegal base64 data.
Run the below command to regenerate the ts-client and patch it:
make ts-client-genThe patch script re-creates ts-client/utils.ts (which exports the shared paramsSerializer) and
rewrites each ts-client/*/rest.ts to wire that serializer into the axios instance.
Always run make ts-client-gen (never ignite generate ts-client on its own) when regenerating,
and commit both the generated files and the patched ones together.
To verify the patch is in place:
make ts-client-testRe-generate cosmos base openapi (service API from cosmos exposed in DCL) using cosmos-swagger-gen.sh from the project root:
- Consider using a docker container built from the provided Dockerfile to have a predictable version of swagger
./scripts/cosmos-swagger-gen.sh base
./scripts/cosmos-swagger-gen.sh txPlease note, that we depend on the CometBFT fork https://github.com/zigbee-alliance/cometbft/releases/tag/v0.37.5 due to hotfixes for tendermint/tendermint#7640 and tendermint/tendermint#7641 required for Light Client Proxy.
Also don't forget to update the link to the CometBFT RPC in Swagger UI.
For more details, please have a look at Cosmos SDK tutorial.