diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f7925ec --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +/.git +/.github diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..75aaa8d --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,67 @@ +name: Build and push docker image + +on: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: nilchain-devnet + +jobs: + docker-build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/NillionNetwork/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + flavor: | + latest=false # Ensure 'latest' tag is not generated + + - name: Set VERSION environment variable + run: | + # Extract the first tag from the generated tags + TAG=$(echo ${{ steps.meta.outputs.tags }} | cut -d ',' -f 1) + TAG=$(echo $TAG | cut -d ':' -f 2) + echo "VERSION=$TAG" >> $GITHUB_ENV + + - name: Build Docker image + uses: docker/build-push-action@v2 + with: + context: . + tags: ${{ steps.meta.outputs.tags }} + build-args: | + VERSION=${{ env.VERSION }} + + - name: Debug tags + run: | + echo "Generated tags: ${{ steps.meta.outputs.tags }}" + echo "Generated labels: ${{ steps.meta.outputs.labels }}" + + - name: List Docker images + run: docker images + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push Docker image + uses: docker/build-push-action@v2 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + build-args: | + VERSION=${{ env.VERSION }} diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml new file mode 100644 index 0000000..84d0cb7 --- /dev/null +++ b/.github/workflows/merge.yaml @@ -0,0 +1,20 @@ +name: Build image +on: + pull_request: + push: + branches: + - main + +jobs: + docker-build: + runs-on: ubuntu-latest + steps: + - name: Build Docker image + uses: docker/build-push-action@v2 + id: build + + - name: Test image is runnable + run: | + docker run --rm ${{steps.build.outputs.imageid}} config view app + + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d4927b5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM ghcr.io/nillionnetwork/nilchaind:v0.2.5 + +WORKDIR /opt/nilchain + +COPY config config +COPY data data + +EXPOSE 26648 26649 26650 + +ENTRYPOINT ["nilchaind", "--home", "/opt/nilchain"] +CMD ["start"] diff --git a/README.md b/README.md index 481009d..04389b6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,35 @@ # nilchain-devnet -A preconfigured nilchain docker image to run as a local devnet + +A preconfigured single node nilchain docker image to be used as a local devnet for testing purposes. + +## Ports + +The nilchain instance can be reached at the following ports: + +| Protocol | Port | +|----------|-------| +| JSON RPC | 26648 | +| gRPC | 26649 | +| REST | 26650 | + +## Chain ID +`nillion-chain-devnet` + +## Stash account + +There's a single "stash" account that contains lots of funds using private key +`97f49889fceed88a9cdddb16a161d13f6a12307c2b39163f3c3c397c3c2d2434`. + +## Overriding configurations + +Configurations can be overridden by using an environment variable named like: + +```bash +NILCHAIND_${CONFIG_FILE_SECTION}_${VARIABLE} +``` + +For example, one can change the commit timeout by running the container like this: + +```bash +docker run --rm -e NILCHAIND_CONSENSUS_TIMEOUT_COMMIT=200ms ghcr.io/nillionnetwork/nilchain-devnet:latest +``` diff --git a/config/addrbook.json b/config/addrbook.json new file mode 100644 index 0000000..878f196 --- /dev/null +++ b/config/addrbook.json @@ -0,0 +1,5 @@ +{ + "key": "2df7e9ed510558a71905f92c", + "addrs": [] +} + diff --git a/config/app.toml b/config/app.toml new file mode 100644 index 0000000..f52f643 --- /dev/null +++ b/config/app.toml @@ -0,0 +1,13 @@ +minimum-gas-prices = "0stake" +query-gas-limit = "0" + +[api] +address = "tcp://0.0.0.0:26650" + +[grpc] +address = "0.0.0.0:26649" +enable = true + +[grpc-web] +enable = true + diff --git a/config/client.toml b/config/client.toml new file mode 100644 index 0000000..791eb6b --- /dev/null +++ b/config/client.toml @@ -0,0 +1,4 @@ +chain-id = "nillion-chain-devnet" +keyring-backend = "test" +node = "tcp://localhost:26657" +broadcast-mode = "sync" diff --git a/config/config.toml b/config/config.toml new file mode 100644 index 0000000..ae7082c --- /dev/null +++ b/config/config.toml @@ -0,0 +1,8 @@ +[consensus] +create_empty_blocks = true +create_empty_blocks_interval = "5s" +skip_timeout_commit = false +timeout_commit = "1s" + +[rpc] +laddr = "tcp://0.0.0.0:26648" diff --git a/config/genesis.json b/config/genesis.json new file mode 100644 index 0000000..15bfd04 --- /dev/null +++ b/config/genesis.json @@ -0,0 +1,346 @@ +{ + "app_name": "nilchaind", + "app_version": "0.2.0", + "genesis_time": "2025-03-19T16:18:50.701624454Z", + "chain_id": "nillion-chain-devnet", + "initial_height": 1, + "app_hash": null, + "app_state": { + "07-tendermint": null, + "auth": { + "params": { + "max_memo_characters": "256", + "tx_sig_limit": "7", + "tx_size_cost_per_byte": "10", + "sig_verify_cost_ed25519": "590", + "sig_verify_cost_secp256k1": "1000" + }, + "accounts": [ + { + "@type": "/cosmos.auth.v1beta1.BaseAccount", + "address": "nillion1mqukqr7d4s3eqhcxwctu7yypm560etp2dghpy6", + "pub_key": null, + "account_number": "0", + "sequence": "0" + } + ] + }, + "authz": { + "authorization": [] + }, + "bank": { + "params": { + "send_enabled": [], + "default_send_enabled": true + }, + "balances": [ + { + "address": "nillion1mqukqr7d4s3eqhcxwctu7yypm560etp2dghpy6", + "coins": [ + { + "denom": "unil", + "amount": "1000000000000000" + } + ] + } + ], + "supply": [ + { + "denom": "unil", + "amount": "1000000000000000" + } + ], + "denom_metadata": [], + "send_enabled": [] + }, + "capability": { + "index": "1", + "owners": [] + }, + "circuit": { + "account_permissions": [], + "disabled_type_urls": [] + }, + "consensus": null, + "distribution": { + "params": { + "community_tax": "0.020000000000000000", + "base_proposer_reward": "0.000000000000000000", + "bonus_proposer_reward": "0.000000000000000000", + "withdraw_addr_enabled": true + }, + "fee_pool": { + "community_pool": [] + }, + "delegator_withdraw_infos": [], + "previous_proposer": "", + "outstanding_rewards": [], + "validator_accumulated_commissions": [], + "validator_historical_rewards": [], + "validator_current_rewards": [], + "delegator_starting_infos": [], + "validator_slash_events": [] + }, + "evidence": { + "evidence": [] + }, + "feegrant": { + "allowances": [] + }, + "feeibc": { + "identified_fees": [], + "fee_enabled_channels": [], + "registered_payees": [], + "registered_counterparty_payees": [], + "forward_relayers": [] + }, + "genutil": { + "gen_txs": [ + { + "body": { + "messages": [ + { + "@type": "/cosmos.staking.v1beta1.MsgCreateValidator", + "description": { + "moniker": "nilchaind", + "identity": "", + "website": "", + "security_contact": "", + "details": "" + }, + "commission": { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.010000000000000000" + }, + "min_self_delegation": "1", + "delegator_address": "", + "validator_address": "nillionvaloper1mqukqr7d4s3eqhcxwctu7yypm560etp2r7xkzy", + "pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "E1YkWeFJjYz9ohld1hIvMtwX3QNQYTOplTPtjDZZf8c=" + }, + "value": { + "denom": "unil", + "amount": "1000000" + } + } + ], + "memo": "7aa7fe3ef81c0e8d13d87c4e1f27608e5f683882@10.0.0.116:26656", + "timeout_height": "0", + "extension_options": [], + "non_critical_extension_options": [] + }, + "auth_info": { + "signer_infos": [ + { + "public_key": { + "@type": "/cosmos.crypto.secp256k1.PubKey", + "key": "Awkj8ucSDFDkKQW4V93SlH9uzO1rsCqrZOY7KOni4G0Q" + }, + "mode_info": { + "single": { + "mode": "SIGN_MODE_DIRECT" + } + }, + "sequence": "0" + } + ], + "fee": { + "amount": [], + "gas_limit": "200000", + "payer": "", + "granter": "" + }, + "tip": null + }, + "signatures": [ + "W9navnPrRCJsTR5HDrELA1bbQebYY/mN2sQ9We30Sw84J2tmGlQ1Mn5NY19LYQv8XP4E+cYwypQgaO25KgGzfg==" + ] + } + ] + }, + "gov": { + "starting_proposal_id": "1", + "deposits": [], + "votes": [], + "proposals": [], + "deposit_params": null, + "voting_params": null, + "tally_params": null, + "params": { + "min_deposit": [ + { + "denom": "unil", + "amount": "10000000" + } + ], + "max_deposit_period": "172800s", + "voting_period": "172800s", + "quorum": "0.334000000000000000", + "threshold": "0.500000000000000000", + "veto_threshold": "0.334000000000000000", + "min_initial_deposit_ratio": "0.000000000000000000", + "proposal_cancel_ratio": "0.500000000000000000", + "proposal_cancel_dest": "", + "expedited_voting_period": "86400s", + "expedited_threshold": "0.667000000000000000", + "expedited_min_deposit": [ + { + "denom": "unil", + "amount": "50000000" + } + ], + "burn_vote_quorum": false, + "burn_proposal_deposit_prevote": false, + "burn_vote_veto": true, + "min_deposit_ratio": "0.010000000000000000" + }, + "constitution": "" + }, + "ibc": { + "client_genesis": { + "clients": [], + "clients_consensus": [], + "clients_metadata": [], + "params": { + "allowed_clients": [ + "*" + ] + }, + "create_localhost": false, + "next_client_sequence": "0" + }, + "connection_genesis": { + "connections": [], + "client_connection_paths": [], + "next_connection_sequence": "0", + "params": { + "max_expected_time_per_block": "30000000000" + } + }, + "channel_genesis": { + "channels": [], + "acknowledgements": [], + "commitments": [], + "receipts": [], + "send_sequences": [], + "recv_sequences": [], + "ack_sequences": [], + "next_channel_sequence": "0", + "params": { + "upgrade_timeout": { + "height": { + "revision_number": "0", + "revision_height": "0" + }, + "timestamp": "600000000000" + } + } + } + }, + "interchainaccounts": { + "controller_genesis_state": { + "active_channels": [], + "interchain_accounts": [], + "ports": [], + "params": { + "controller_enabled": true + } + }, + "host_genesis_state": { + "active_channels": [], + "interchain_accounts": [], + "port": "icahost", + "params": { + "host_enabled": true, + "allow_messages": [ + "*" + ] + } + } + }, + "meta": { + "resources": [] + }, + "mint": { + "minter": { + "inflation": "0.130000000000000000", + "annual_provisions": "0.000000000000000000" + }, + "params": { + "mint_denom": "unil", + "inflation_rate_change": "0.130000000000000000", + "inflation_max": "0.200000000000000000", + "inflation_min": "0.070000000000000000", + "goal_bonded": "0.670000000000000000", + "blocks_per_year": "6311520" + } + }, + "params": null, + "slashing": { + "params": { + "signed_blocks_window": "100", + "min_signed_per_window": "0.500000000000000000", + "downtime_jail_duration": "600s", + "slash_fraction_double_sign": "0.050000000000000000", + "slash_fraction_downtime": "0.010000000000000000" + }, + "signing_infos": [], + "missed_blocks": [] + }, + "staking": { + "params": { + "unbonding_time": "1814400s", + "max_validators": 100, + "max_entries": 7, + "historical_entries": 10000, + "bond_denom": "unil", + "min_commission_rate": "0.000000000000000000" + }, + "last_total_power": "0", + "last_validator_powers": [], + "validators": [], + "delegations": [], + "unbonding_delegations": [], + "redelegations": [], + "exported": false + }, + "transfer": { + "port_id": "transfer", + "denom_traces": [], + "params": { + "send_enabled": true, + "receive_enabled": true + }, + "total_escrowed": [] + }, + "upgrade": {}, + "vesting": {} + }, + "consensus": { + "params": { + "block": { + "max_bytes": "22020096", + "max_gas": "-1" + }, + "evidence": { + "max_age_num_blocks": "100000", + "max_age_duration": "172800000000000", + "max_bytes": "1048576" + }, + "validator": { + "pub_key_types": [ + "ed25519" + ] + }, + "version": { + "app": "0" + }, + "abci": { + "vote_extensions_enable_height": "0" + } + } + } +} + diff --git a/config/gentx/gentx-7aa7fe3ef81c0e8d13d87c4e1f27608e5f683882.json b/config/gentx/gentx-7aa7fe3ef81c0e8d13d87c4e1f27608e5f683882.json new file mode 100644 index 0000000..33e4b09 --- /dev/null +++ b/config/gentx/gentx-7aa7fe3ef81c0e8d13d87c4e1f27608e5f683882.json @@ -0,0 +1,62 @@ +{ + "body": { + "messages": [ + { + "@type": "/cosmos.staking.v1beta1.MsgCreateValidator", + "description": { + "moniker": "nilchaind", + "identity": "", + "website": "", + "security_contact": "", + "details": "" + }, + "commission": { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.010000000000000000" + }, + "min_self_delegation": "1", + "delegator_address": "", + "validator_address": "nillionvaloper1mqukqr7d4s3eqhcxwctu7yypm560etp2r7xkzy", + "pubkey": { + "@type": "/cosmos.crypto.ed25519.PubKey", + "key": "E1YkWeFJjYz9ohld1hIvMtwX3QNQYTOplTPtjDZZf8c=" + }, + "value": { + "denom": "unil", + "amount": "1000000" + } + } + ], + "memo": "7aa7fe3ef81c0e8d13d87c4e1f27608e5f683882@10.0.0.116:26656", + "timeout_height": "0", + "extension_options": [], + "non_critical_extension_options": [] + }, + "auth_info": { + "signer_infos": [ + { + "public_key": { + "@type": "/cosmos.crypto.secp256k1.PubKey", + "key": "Awkj8ucSDFDkKQW4V93SlH9uzO1rsCqrZOY7KOni4G0Q" + }, + "mode_info": { + "single": { + "mode": "SIGN_MODE_DIRECT" + } + }, + "sequence": "0" + } + ], + "fee": { + "amount": [], + "gas_limit": "200000", + "payer": "", + "granter": "" + }, + "tip": null + }, + "signatures": [ + "W9navnPrRCJsTR5HDrELA1bbQebYY/mN2sQ9We30Sw84J2tmGlQ1Mn5NY19LYQv8XP4E+cYwypQgaO25KgGzfg==" + ] +} diff --git a/config/node_key.json b/config/node_key.json new file mode 100644 index 0000000..088e3cf --- /dev/null +++ b/config/node_key.json @@ -0,0 +1,7 @@ +{ + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "S4O4hrVjT6L1O0GVsOMqMZVsIF6dEPjU7yZGQc80jnuHpKdk44CSKk8oYxuu4wTeg+NBTcYzuRQZIC/nUF/bFQ==" + } +} + diff --git a/config/priv_validator_key.json b/config/priv_validator_key.json new file mode 100644 index 0000000..872031b --- /dev/null +++ b/config/priv_validator_key.json @@ -0,0 +1,12 @@ +{ + "address": "FB215FA2F3D540EC5FD2AE2B7A897AE4CB347191", + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "E1YkWeFJjYz9ohld1hIvMtwX3QNQYTOplTPtjDZZf8c=" + }, + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "yPNDZj8f6vAJDPrLN+WmZRGpPf1j4pWeRCZ4GGkb10wTViRZ4UmNjP2iGV3WEi8y3BfdA1BhM6mVM+2MNll/xw==" + } +} + diff --git a/data/priv_validator_state.json b/data/priv_validator_state.json new file mode 100644 index 0000000..0e4dc01 --- /dev/null +++ b/data/priv_validator_state.json @@ -0,0 +1,7 @@ +{ + "height": "1", + "round": 0, + "step": 0, + "signature": "0T9u0+5C1uEnW5W0qWYGBlIchYzgf5jNYTBM7xPsw7LRvoWZumNY2fq63vnrVRt7IePBtrsgNcsCi9K/B+W+CA==", + "signbytes": "78080211150000000000000022480A208890D445F190E83AC8F6144E6A30DD682B2FB9F64CEC7E3288F7A45FD75958F812240801122058047F9E8096F3E0301304B3A777AA9C4F318635B54A0607855777CB5F28E9D32A0B0893E0EBBE06109BAEFA0D32146E696C6C696F6E2D636861696E2D6465766E6574" +}