Akash Blockchain Build
Overview
Follow the steps in this guide to scaffold and build an Akash blockchain for testing purposes.
Sections:
- Environment Overview
- Akash Blockchain Build
- RPC Node Build
- Akash Provider Build
- CosmoVisor Network Upgrade Test
Environment Overview
The topology used in this guide to build an Akash blockchain instance are as follows. Alternate toplogies could be used including a single host Kubernetes environment.
Hosts
- Single Kubernetes master node
- Single Kubernetes worker node
Components
- Akssh Validator created as a Kubernetes stateful set
- Akash RPC node created as a Kubernetes stateful set
- Akash Provider built using Helm Charts and within the same Kubernetes cluster as the validator
Akash Blockchain Build
STEP 1 - Build Kubernetes Cluster
For this build we will use a K3s cluster.
Follow the steps in this Akash documentation guide to build the K3s cluster.
The build in this guide uses a two cluster topolgy with a single control-plane and single dedicated worker node.
STEP 2 - Deploy Initial Validator
NOTE - example blockchain deployed on Google Cloud (GCP) and thus manually creating Kubernetes Persistent Volumes. In other environments this may be seen as unnecessary and may allow Container Storage Interface (CSI) to auto provision the PVs.
Create Mount Point Directories
- Create the
/mnt/validatordirectory on each of the Kubernetes hosts
mkdir -p /mnt/validator
Create the Persistent Volumes
- Create the Kubernetes Persistent Volumes using the following manifest
- Adjust the node names in the
nodeAffinitystanza to reflect the actual hostnames in your cluster - Add additional sections if mutliple validators are in the genesis
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-validator-node1
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: validator-storage
local:
path: /mnt/validator
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- master
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-validator-node2
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: validator-storage
local:
path: /mnt/validator
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker
Create the Validtor Stateful Set
# StatefulSet for validator-01 service
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: validator-01
namespace: akash-services
spec:
serviceName: "validator-01-service"
replicas: 1
selector:
matchLabels:
app: validator-01
template:
metadata:
labels:
app: validator-01
spec:
containers:
- name: validator-01
image: "ghcr.io/akash-network/cosmos-omnibus:v0.4.11-rc1-generic"
command: ["/bin/sh", "-c"]
args: ["sleep infinity"]
env:
- name: PROJECT_BIN
value: akash
- name: BINARY_URL
value: "https://github.com/akash-network/node/releases/download/v1.0.0-rc10/akash_1.0.0-rc10_linux_amd64.zip" # Updated URL
- name: MONIKER
value: validator-01
- name: MINIMUM_GAS_PRICES
value: 0.025uakt
- name: FASTSYNC_VERSION
value: v0
- name: CHAIN_ID
value: testnet-6
- name: COSMOVISOR_ENABLED
value: "1"
- name: DAEMON_ALLOW_DOWNLOAD_BINARIES
value: "true"
- name: DAEMON_RESTART_AFTER_UPGRADE
value: "true"
- name: DAEMON_LOG_BUFFER_SIZE
value: "512"
- name: UNSAFE_SKIP_BACKUP
value: "true"
ports:
- name: p2p
containerPort: 26656
- name: rpc
containerPort: 26657
volumeMounts:
- name: data
mountPath: /root/.akash
nodeSelector:
kubernetes.io/hostname: worker-01
volumeClaimTemplates:
- metadata:
name: data
annotations:
volume.alpha.kubernetes.io/storage-class: validator-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
storageClassName: validator-storage
---
apiVersion: v1
kind: Service
metadata:
name: validator-01
namespace: akash-services
spec:
selector:
app: validator-01
ports:
- protocol: TCP
port: 26656
targetPort: 26656
name: p2p
- protocol: TCP
port: 26657
targetPort: 26657
name: rpc
Verify Validator Deployment
ENSURE PVC BINDING
kubectl get pvc -n akash-services
EXPECTED/EXAMPLE OUTPUT
root@blockchain:~# kubectl get pvc -n akash-services
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
data-validator-01-0 Bound validator-pv-1 50Gi RWO validator-storage <unset> 62s
Verify Validator Pod
kubectl get pods -n akash-services
EXPECTED/EXAMPLE OUTPUT
root@blockchain:~# kubectl get pods -n akash-services
NAME READY STATUS RESTARTS AGE
validator-01-0 1/1 Running 0 6m3s
STEP 3 - Configure the Initial Validator
NOTE - ensure the validator pod created in the prior step is in a
Runningstatus prior to completing the steps in this section
Create a Session into the Validator Pod
NOTE - following this section all remaining commands in this seciton shold be conducted from within the validator pod CLI session established
kubectl exec -ti validator-01-0 -n akash-services -- bash
Install the Akash Node Binary within the Pod
NOTE - replace the specific binary link used in the example with the current/desired binary version
cd
wget -c https://github.com/akash-network/node/releases/download/v0.32.2/akash_0.32.2_linux_amd64.zip
unzip akash_0.32.2_linux_amd64.zip
install akash /usr/local/bin/
rm akash_0.32.2_linux_amd64.zip akash
Confirm Akash Binary Installation
akash version
EXPECTED/EXAMPLE OUTPUT
root@validator-01-0:~# akash version
v0.32.2
STEP 4 - Initialize the New Blockchain
Ensure the .akash Directory is Empty
rm -rf ~/.akash/*
Create Validator Initial Genesis File
- Create genesis.json with the node/validator with the chain ID of
sandbox-01and a moniker ofvalidator-01 - Adjust the chain ID as necessary for specific network build
- The genesis will be further updated in subsequent steps
akash genesis init --chain-id sandbox-01 validator-01
EXAMPLE/EXPECTED OUTPUT
{"app_message":{"agov":{"deposit_params":{"min_initial_deposit_rate":"0.400000000000000000"}},"astaking":{"params":{"min_commission_rate":"0.050000000000000000"}},"audit":{"attributes":[]},"auth":{"accounts":[],"params":{"max_memo_characters":"256","sig_verify_cost_ed25519":"590","sig_verify_cost_secp256k1":"1000","tx_sig_limit":"7","tx_size_cost_per_byte":"10"}},"authz":{"authorization":[]},"bank":{"balances":[],"denom_metadata":[],"params":{"default_send_enabled":true,"send_enabled":[]},"supply":[]},"capability":{"index":"1","owners":[]},"cert":{"certificates":[]},"crisis":{"constant_fee":{"amount":"1000","denom":"stake"}},"deployment":{"deployments":[],"params":{"min_deposits":[{"amount":"500000","denom":"uakt"}]}},"distribution":{"delegator_starting_infos":[],"delegator_withdraw_infos":[],"fee_pool":{"community_pool":[]},"outstanding_rewards":[],"params":{"base_proposer_reward":"0.010000000000000000","bonus_proposer_reward":"0.040000000000000000","community_tax":"0.020000000000000000","withdraw_addr_enabled":true},"previous_proposer":"","validator_accumulated_commissions":[],"validator_current_rewards":[],"validator_historical_rewards":[],"validator_slash_events":[]},"escrow":{"accounts":[],"payments":[]},"evidence":{"evidence":[]},"feegrant":{"allowances":[]},"genutil":{"gen_txs":[]},"gov":{"deposit_params":{"max_deposit_period":"172800s","min_deposit":[{"amount":"10000000","denom":"stake"}]},"deposits":[],"proposals":[],"starting_proposal_id":"1","tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"votes":[],"voting_params":{"voting_period":"172800s"}},"ibc":{"channel_genesis":{"ack_sequences":[],"acknowledgements":[],"channels":[],"commitments":[],"next_channel_sequence":"0","receipts":[],"recv_sequences":[],"send_sequences":[]},"client_genesis":{"clients":[],"clients_consensus":[],"clients_metadata":[],"create_localhost":false,"next_client_sequence":"0","params":{"allowed_clients":["06-solomachine","07-tendermint"]}},"connection_genesis":{"client_connection_paths":[],"connections":[],"next_connection_sequence":"0","params":{"max_expected_time_per_block":"30000000000"}}},"inflation":{"params":{"inflation_decay_factor":"2.000000000000000000","initial_inflation":"100.000000000000000000","variance":"0.050000000000000000"}},"market":{"bids":[],"leases":[],"orders":[],"params":{"bid_min_deposit":{"amount":"500000","denom":"uakt"},"order_max_bids":20}},"mint":{"minter":{"annual_provisions":"0.000000000000000000","inflation":"0.130000000000000000"},"params":{"blocks_per_year":"6311520","goal_bonded":"0.670000000000000000","inflation_max":"0.200000000000000000","inflation_min":"0.070000000000000000","inflation_rate_change":"0.130000000000000000","mint_denom":"stake"}},"params":null,"provider":{"providers":[]},"slashing":{"missed_blocks":[],"params":{"downtime_jail_duration":"600s","min_signed_per_window":"0.500000000000000000","signed_blocks_window":"100","slash_fraction_double_sign":"0.050000000000000000","slash_fraction_downtime":"0.010000000000000000"},"signing_infos":[]},"staking":{"delegations":[],"exported":false,"last_total_power":"0","last_validator_powers":[],"params":{"bond_denom":"stake","historical_entries":10000,"max_entries":7,"max_validators":100,"unbonding_time":"1814400s"},"redelegations":[],"unbonding_delegations":[],"validators":[]},"take":{"params":{"default_take_rate":20,"denom_take_rates":[{"denom":"uakt","rate":2}]}},"transfer":{"denom_traces":[],"params":{"receive_enabled":true,"send_enabled":true},"port_id":"transfer"},"upgrade":{},"vesting":{}},"chain_id":"sandbox-01","gentxs_dir":"","moniker":"validator-01","node_id":"af88523de02b3943d0e29c8b4d97408b3f0c1098"}
Recover accounts or create anew
export AKASH_KEYRING_BACKEND=test
akash keys add default
Create a single genesis account with 100 Million AKT
akash genesis add-account $(akash keys show default -a) 100000000000000uakt
Create initial validator with 1 Million AKT staked
akash genesis gentx default 1000000000000uakt --chain-id sandbox-01
Run collect-gentxs
akash genesis collect
Update Expedited Voting Period (Testnet Only)
- In a testnet environment, it is useful to reduce the expedited governance proposal voting period from the default 24 hours to 30 minutes
- This allows for quicker parameter updates and testing of governance proposals
# Update the expedited_voting_period from 86400s (24 hours) to 1800s (30 minutes)
sed -i 's/"expedited_voting_period": "86400s"/"expedited_voting_period": "1800s"/g' ~/.akash/config/genesis.json
# Verify the change
grep "expedited_voting_period" ~/.akash/config/genesis.json
EXPECTED/EXAMPLE OUTPUT
"expedited_voting_period": "1800s",
Capture the Node ID of the Validator**
- Store the captured output/node ID exposed in this step for use in subsequent steps
akash tendermint show-node-id
EXAMPLE/EXPECTED OUTPUT
NOTE - your Node ID will be different/unique
root@validator-01-0:~# akash tendermint show-node-id
af88523de02b3943d0e29c8b4d97408b3f0c1098
STEP 5 - Initialize the Blockchain
NOTE - conduct the steps in this section from the Kubernetes control-plane node
Update Validator Statefull Set
- Update the Validator stateful set with removal of initial commands that initially put the associated pod in a sleep infinity condition to allow access and configuration.
- Now with the node configured we can remove sleep infinity and allow the pod to initialize the first validator on the network
kubectl patch statefulset validator-01 -n akash-services --type='json' -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}, {"op": "remove", "path": "/spec/template/spec/containers/0/args"}]'
Verify the Validator is Writing Blocks
- Verify that the validator is writing blocks to the blochchain by continually monitoring the validator pod
kubectl logs validator-01-0 -n akash-services -f
EXAMPLE/EXPECTED OUTPUT
- This is an example message from a single blockchain write and for a single block. There should be incrementing block numbers/writes every several second and each with this type of log message.
INF committed state app_hash=B423ACA69FB037927DCD3FEBFD7B70F448673372380811273F7E3096F1DFA648 height=39 module=state num_txs=0
INF indexed block exents height=39 module=txindex
INF Timed out dur=4986.142971 height=40 module=consensus round=0 step=1
RPC Node Build
- With a functional/live blockchain, we will launch the network's first RPC node for use by the Akash Provider we will build eventually and for other network query/transaction operations
NOTE - the RPC Node build uses a similar methodology to the Validator build. We deploy the pod initially in a
sleep infinitystate to allow manual configuration, then remove the sleep command once the node is properly initialized. This is necessary because current cosmos-omnibus images use the legacyakash initcommand instead of the newerakash genesis initsyntax required by recent Akash node versions.
STEP 1 - Create Persistent Volumes
NOTE - example blockchain deployed on Google Cloud (GCP) and thus manually creating Kubernetes Persistent Volumes. In other environments this may be seen as unnecessary and may allow Container Storage Interface (CSI) to auto provision the PVs.
Create Mount Point Directories
- Create the
/mnt/rpcdirectory on each of the Kubernetes hosts
mkdir -p /mnt/rpc
Create the Persistent Volumes
- Create the Kubernetes Persistent Volumes using the following manifest
- Adjust the node names in the
nodeAffinitystanza to reflect the actual hostnames in your cluster
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-rpc-node1
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: akash-nodes
local:
path: /mnt/rpc
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- master
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-rpc-node2
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: akash-nodes
local:
path: /mnt/rpc
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker
STEP 2 - Deploy RPC Node Stateful Set
Create the RPC Node Stateful Set
- Prior to creating this RPC Node stateful set via the manifest below - ensure to update these fields:
image- uses latest stable Omnibus generic image (v1.2.36-generic as of this writing). Find latest versions hereBINARY_URL- update with current/desired Akash Node versionP2P_SEEDS,AKASH_P2P_PRIVATE_PEER_IDS,AKASH_P2P_PERSISTENT_PEERS,AKASH_P2P_UNCONDITIONAL_PEER_IDS- update each of these env variables with the validator node ID captured in theCapture the Node ID of the ValidatorstepCHAIN_ID- update to match your testnet chain IDGENESIS_URL- replace with the URL hosting the genesis.json filenodeSelector- update hostname to match your cluster worker node
NOTE - the manifest uses
sleep infinityto allow initial configuration. The node will be started in a later step after manual initialization.
# StorageClass for akash nodes
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: akash-nodes
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
# StatefulSet for rpc service
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rpc
namespace: akash-services
spec:
serviceName: "rpc-service"
replicas: 1
selector:
matchLabels:
app: rpc
template:
metadata:
labels:
app: rpc
spec:
containers:
- name: rpc
image: "ghcr.io/akash-network/cosmos-omnibus:v1.2.36-generic"
command: ["/bin/sh", "-c"]
args: ["sleep infinity"]
env:
- name: PROJECT_BIN
value: akash
- name: BINARY_URL
value: "https://github.com/akash-network/node/releases/download/v0.32.2/akash_0.32.2_linux_amd64.zip"
- name: MONIKER
value: rpc-01
- name: MINIMUM_GAS_PRICES
value: 0.025uakt
- name: FASTSYNC_VERSION
value: v0
- name: P2P_SEEDS
value: <VALIDATOR_NODE_ID>@validator-01:26656
- name: AKASH_P2P_PRIVATE_PEER_IDS
value: <VALIDATOR_NODE_ID>
- name: AKASH_P2P_PERSISTENT_PEERS
value: <VALIDATOR_NODE_ID>@validator-01:26656
- name: AKASH_P2P_UNCONDITIONAL_PEER_IDS
value: <VALIDATOR_NODE_ID>
- name: CHAIN_ID
value: sandbox-01
- name: GENESIS_URL
value: "<YOUR_GENESIS_URL>"
- name: AKASH_API_ENABLE
value: "true"
- name: AKASH_PRUNING
value: custom
- name: AKASH_PRUNING_INTERVAL
value: "10"
- name: AKASH_PRUNING_KEEP_EVERY
value: "500"
- name: AKASH_PRUNING_KEEP_RECENT
value: "100"
- name: AKASH_STATE_SYNC_SNAPSHOT_INTERVAL
value: "500"
- name: COSMOVISOR_ENABLED
value: "0"
- name: DAEMON_ALLOW_DOWNLOAD_BINARIES
value: "true"
- name: DAEMON_RESTART_AFTER_UPGRADE
value: "true"
- name: DAEMON_LOG_BUFFER_SIZE
value: "512"
- name: UNSAFE_SKIP_BACKUP
value: "true"
volumeMounts:
- name: data
mountPath: /root/.akash
ports:
- name: api
containerPort: 1317
- name: grpc
containerPort: 9090
- name: p2p
containerPort: 26656
- name: rpc
containerPort: 26657
nodeSelector:
kubernetes.io/hostname: worker
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
storageClassName: akash-nodes
---
# ClusterIP Service for internal access
apiVersion: v1
kind: Service
metadata:
name: rpc
namespace: akash-services
spec:
selector:
app: rpc
ports:
- protocol: TCP
port: 1317
targetPort: 1317
name: api
- protocol: TCP
port: 9090
targetPort: 9090
name: grpc
- protocol: TCP
port: 26656
targetPort: 26656
name: p2p
- protocol: TCP
port: 26657
targetPort: 26657
name: rpc
Verify RPC Node Deployment
ENSURE PVC BINDING
kubectl get pvc -n akash-services
EXPECTED/EXAMPLE OUTPUT
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-rpc-0 Bound local-pv-rpc-node1 100Gi RWO akash-nodes 30s
Verify RPC Node Pod
kubectl get pods -n akash-services
EXPECTED/EXAMPLE OUTPUT
NAME READY STATUS RESTARTS AGE
validator-01-0 1/1 Running 0 10m
rpc-0 1/1 Running 0 60s
STEP 3 - Configure the RPC Node
NOTE - ensure the RPC Node pod created in the prior step is in a
Runningstatus prior to completing the steps in this section
Create a Session into the RPC Node Pod
NOTE - following this section all remaining commands in this section should be conducted from within the RPC Node pod CLI session established
kubectl exec -ti rpc-0 -n akash-services -- bash
Install the Akash Node Binary within the Pod
NOTE - replace the specific binary link used in the example with the current/desired binary version matching your testnet
cd
wget -c https://github.com/akash-network/node/releases/download/v0.32.2/akash_0.32.2_linux_amd64.zip
unzip akash_0.32.2_linux_amd64.zip
install akash /usr/local/bin/
rm akash_0.32.2_linux_amd64.zip akash
Confirm Akash Binary Installation
akash version
EXPECTED/EXAMPLE OUTPUT
root@rpc-0:~# akash version
v0.32.2
Initialize the RPC Node
- The
GENESIS_URLenv var in the manifest causes omnibus to download the correct genesis.json file on pod startup - The
akash genesis initcommand will overwrite this file, so we backup first and restore after initialization - Adjust the chain ID and moniker to match your network
# Backup the genesis file downloaded via GENESIS_URL
cp ~/.akash/config/genesis.json /tmp/genesis.json.bak
# Initialize the node (creates config structure but overwrites genesis)
akash genesis init --chain-id sandbox-01 rpc-01
# Restore the correct genesis file
cp /tmp/genesis.json.bak ~/.akash/config/genesis.json
Configure External Access Bindings
- By default, the RPC and API endpoints bind to localhost. Update to allow external access:
# Update RPC binding to allow external connections
sed -i 's/laddr = "tcp:\/\/127.0.0.1:26657"/laddr = "tcp:\/\/0.0.0.0:26657"/g' ~/.akash/config/config.toml
# Update API binding in app.toml
sed -i 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:1317"/g' ~/.akash/config/app.toml
# Update gRPC binding in app.toml
sed -i 's/address = "localhost:9090"/address = "0.0.0.0:9090"/g' ~/.akash/config/app.toml
# Ensure API is enabled
sed -i '/^\[api\]/,/^\[/ s/enable = false/enable = true/' ~/.akash/config/app.toml
# Ensure gRPC is enabled
sed -i '/^\[grpc\]/,/^\[/ s/enable = false/enable = true/' ~/.akash/config/app.toml
Exit the RPC Node Pod
exit
STEP 4 - Start the RPC Node
NOTE - conduct the steps in this section from the Kubernetes control-plane node
Update RPC Node StatefulSet
- Update the RPC Node stateful set with removal of initial commands that initially put the associated pod in a sleep infinity condition to allow access and configuration
- Now with the node configured we can remove sleep infinity and allow the pod to start syncing
kubectl patch statefulset rpc -n akash-services --type='json' -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}, {"op": "remove", "path": "/spec/template/spec/containers/0/args"}]'
Verify the RPC Node is Syncing
- Monitor the RPC node logs to verify it's connecting to the validator and syncing blocks
kubectl logs rpc-0 -n akash-services -f
EXPECTED/EXAMPLE OUTPUT
- You should see the node connecting to the validator and syncing blocks:
INF Starting Node service impl=Node
INF Connecting to peer addr=<VALIDATOR_NODE_ID>@validator-01:26656
INF committed state app_hash=... height=100 module=state num_txs=0
STEP 5 - Confirm RPC Node Status
Create a Session into the RPC Node Pod
kubectl exec -ti rpc-0 -n akash-services -- bash
Query Node Status
- Checking the RPC node status will display latest block height received, if the RPC Node is in sync, etc
akash status
EXAMPLE/EXPECTED OUTPUT
- The node should eventually reach a status of
"catching_up":falseas demonstrated in the JSON output below - Search for
catching_upto see example/expected status. It may take the RPC node some time to catch up depending on how many blocks are on the blockchain. Should sync very quickly if you are performing this build shortly after the chain initiation.
{"NodeInfo":{"protocol_version":{"p2p":"8","block":"11","app":"0"},"id":"7cacf5b9b4609955651832dc956462748e6d5683","listen_addr":"tcp://0.0.0.0:26656","network":"sandbox-01","version":"0.34.27","channels":"40202122233038606100","moniker":"rpc-01","other":{"tx_index":"on","rpc_address":"tcp://0.0.0.0:26657"}},"SyncInfo":{"latest_block_hash":"354FE2E80583C4C5035473557C1268C5CEB4EA020A04ED2F23B1C8A64840538F","latest_app_hash":"C8D05A64741A9F80003482397A62C47BA8AF71198AB46901EFD4FBB2666A9A84","latest_block_height":"4055","latest_block_time":"2024-03-23T01:45:43.804861718Z","earliest_block_hash":"667680E786A4F4D371202BA1D184433405161F9A2775283BA79AB8937EF08F53","earliest_app_hash":"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855","earliest_block_height":"1","earliest_block_time":"2024-03-22T18:25:20.428854275Z","catching_up":false},"ValidatorInfo":{"Address":"19764CA8E5E85F2186DAF1CF64923D99D9AFCB17","PubKey":{"type":"tendermint/PubKeyEd25519","value":"hv05xEVMkG5zYA7m6MiiGVLncTUn3FssG1HO1NnSIts="},"VotingPower":"0"}}
STEP 6 - Create NodePort Service for External Access (Optional)
- If external access to the RPC node is required, create a NodePort service
- This is necessary for external validators to peer with your RPC node and for external clients to query the network
NOTE - the
externalTrafficPolicy: Localsetting is critical for P2P protocol compatibility. Without this setting, kube-proxy's SNAT can interfere with the Tendermint P2P handshake.
Create the NodePort Service Manifest
apiVersion: v1
kind: Service
metadata:
name: rpc-nodeport
namespace: akash-services
spec:
type: NodePort
externalTrafficPolicy: Local # Critical for P2P protocol compatibility
selector:
app: rpc
ports:
- protocol: TCP
port: 26656 # P2P port
targetPort: 26656 # Pod P2P port
nodePort: 30656 # External P2P access
name: p2p
- protocol: TCP
port: 26657 # RPC port
targetPort: 26657 # Pod RPC port
nodePort: 30657 # External RPC access
name: rpc
- protocol: TCP
port: 1317 # API port
targetPort: 1317
nodePort: 30317 # External API access
name: api
- protocol: TCP
port: 9090 # gRPC port
targetPort: 9090
nodePort: 30090 # External gRPC access
name: grpc
Apply the NodePort Service
kubectl apply -f rpc-nodeport-service.yaml
Verify the NodePort Service
kubectl get svc -n akash-services
EXPECTED/EXAMPLE OUTPUT
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rpc ClusterIP 10.233.27.177 <none> 1317/TCP,9090/TCP,26656/TCP,26657/TCP 10m
rpc-nodeport NodePort 10.233.45.89 <none> 26656:30656/TCP,26657:30657/TCP,1317:30317/TCP,9090:30090/TCP 30s
validator-01 ClusterIP 10.233.12.34 <none> 26656/TCP,26657/TCP 30m
DNS Configuration (If Required)
To make the RPC node accessible via a domain name (e.g., rpc.dev.akash.pub):
- Point the DNS A record to your Kubernetes node's external IP
- Access endpoints:
- P2P:
rpc.dev.akash.pub:30656 - RPC:
rpc.dev.akash.pub:30657 - API:
rpc.dev.akash.pub:30317 - gRPC:
rpc.dev.akash.pub:30090
- P2P:
Test External Access
# Test RPC endpoint
curl http://<NODE_EXTERNAL_IP>:30657/status
# Test API endpoint
curl http://<NODE_EXTERNAL_IP>:30317/cosmos/base/tendermint/v1beta1/node_info
Akash Provider Build
- Build the Akash Provider via Helm Charts and via this documentation
- Conduct build from control-plane node of pre-existing Kubernetes cluster
- Review additional notes section below for guidance on setting up a provider for test blockchain use
Additional Notes Provider Build
Ingress Rules
- To expose the validator to the outside world, update the ingress TCP rules such as the following example
- Ensure the new configmap settings have been applied post build via -
kubectl get svc -n ingress-nginx- and check exposed TCP ports - Testing of external validator access is possible via (I.e.) -
curl http://34.172.54.64:30057/status
tcp:
"8443": "akash-services/akash-provider:8443"
"8444": "akash-services/akash-provider:8444"
"30056": "akash-services/validator-01:26656"
"30057": "akash-services/validator-01:26657"
Provider Account Creation and Configuration
- Install
provider-servicesbinary and create/import provider Akash address - Configure environment variables as follows replacing the account address with your provider address
AKASH_KEY_NAME=default
AKASH_KEYRING_BACKEND=test
export AKASH_CHAIN_ID="sandbox-01"
export AKASH_ACCOUNT_ADDRESS=akash1mtnuc449l0mckz4cevs835qg72nvqwlul5wzyf
export AKASH_NODE=http://rpc:26657
export AKASH_GAS=auto
export AKASH_GAS_ADJUSTMENT=1.5
export AKASH_GAS_PRICES=0.025uakt
export AKASH_SIGN_MODE=amino-json
Fund Provider Account
- Import the validator account to send funds to the provider account
- Enter the mnemonic for the account when prompted
- Example:
provider-services keys add validator --recover
- Transfer funds from the valiadtor account to the provider account
- Example:
provider-services tx send <valdiator-address> <provider-address> 100000000uakt
Chain ID Specification
- Ensure the chain ID is specified as
sandbox-01in theprovider.yamlfile such as (replace address and other elements as necessary):
---
from: "$ACCOUNT_ADDRESS"
key: "$(cat ~/key.pem | openssl base64 -A)"
keysecret: "$(echo $KEY_PASSWORD | openssl base64 -A)"
domain: "$DOMAIN"
node: "$NODE"
withdrawalperiod: 12h
chainid: sandbox-01
attributes:
- key: region
value: "us-central"
- key: host
value: akash
- key: tier
value: community
- key: organization
value: "akashtesting"
CosmoVisor Network Upgrade Test
Create Proposal, Deposit, and Vote
Notes on Proposal Customization
Create a network upgrade proposal on the blockchain using the Example Proposal below. This JSON proposal example should be updated for your purposes in the following sections:
Example Proposal
NOTES:
- Ensure to use the raw content URL such as:
'https://raw.githubusercontent.com/akash-network/net/main/sandbox/upgrades/v0.36.0/info.json`
- Default voting period is 10 minutes
akash tx gov submit-proposal software-upgrade v0.34.0 --title "v0.34.0" --description "SW upgrade proposal for v0.34.0" --upgrade-height 1857050 --upgrade-info "https://raw.githubusercontent.com/akash-network/net/main/sandbox/upgrades/v0.34.0/info.json" --deposit 4000000uakt
Example Query Proposal
akash query gov proposal 4 | jq -r .
Example Deposit
akash tx gov deposit 4 10000000uakt
Example Query Proposal to Validate Deposit
akash query gov proposal 4 | jq -r .
Example Vote
- Repeat across sufficient number of accounts to reach consesus
akash tx gov vote 4 yes
Example Query Tally/Votes
akash query gov tally 4 | jq -r .
Upgrade Validations
Validator Logs Showing Upgrade Initiation
INF service stop impl={"Dir":"/root/.akash/data/cs.wal","Head":{"ID":"6ZRpIvNrxK4C:/root/.akash/data/cs.wal/wal","Path":"/root/.akash/data/cs.wal/wal"},"ID":"group:6ZRpIvNrxK4C:/root/.akash/data/cs.wal/wal","Logger":{}} module=consensus msg={} wal=/root/.akash/data/cs.wal/wal
4:11PM INF daemon shutting down in an attempt to restart module=cosmovisor
4:12PM INF no upgrade binary found, beginning to download it module=cosmovisor
4:12PM INF downloading binary complete module=cosmovisor
4:12PM INF pre-upgrade command does not exist. continuing the upgrade. module=cosmovisor
4:12PM INF upgrade detected, relaunching app=akash module=cosmovisor
4:12PM INF running app args=["start"] module=cosmovisor path=/root/.akash/cosmovisor/upgrades/v0.34.0/bin/akash
root-validator1-1 | INF applying upgrade "v0.34.0" at height: 628
Additional Validations
NOTE - in testing
akash statusdid not show new version despite successful Cosmovisor upgrade. This section provides additional verification examples - with example output - to ensure the upgrade was completed.
ps -ef | grep akash
root 89 1 12 16:12 ? 00:02:02 /root/.akash/cosmovisor/upgrades/v0.34.0/bin/akash start
root 229 169 0 16:28 pts/1 00:00:00 grep akash
/root/.akash/cosmovisor/upgrades/v0.34.0/bin/akash version
v0.34.1