Step-by-step guides for common development and debugging scenarios.
- Upgrade Testing Workflow
- Quick Upgrade (Skip Governance)
- Resuming Interrupted Upgrades
- Key Export Workflow
- State Reset Workflow
- Docker vs Local ExecutionMode
- dvb CLI Workflows (Daemon Mode)
Test software upgrades using expedited governance proposals.
The upgrade workflow allows you to test chain upgrades in a controlled environment:
- Deploy devnet with initial version
- Submit upgrade proposal via governance
- Validators vote YES automatically
- Chain halts at upgrade height
- Switch to new binary/image
- Chain resumes with upgraded software
# Deploy with specific initial version
devnet-builder deploy --image <docker-registry>/<network-image>:v1.0.0# Check status
devnet-builder status
# Verify block production
curl -s http://localhost:26657/status | jq '.result.sync_info.latest_block_height'# Start upgrade to new version (interactive binary selection)
devnet-builder upgrade \
--name v2-upgrade \
--version v2.0.0
# Or specify image directly
devnet-builder upgrade \
--name v2-upgrade \
--image <docker-registry>/<network-image>:v2.0.0This will:
- Submit an expedited governance proposal
- All validators vote YES automatically
- Wait for upgrade height
- Restart nodes with new image
# Watch logs during upgrade
devnet-builder logs -f
# Check upgrade progress
devnet-builder status
# Show detailed upgrade status
devnet-builder upgrade --show-status# Check chain is producing blocks
curl -s http://localhost:26657/status | jq '.result.sync_info'
# Verify version
curl -s http://localhost:26657/abci_info | jq '.result.response.version'For debugging upgrade issues, export genesis before and after:
devnet-builder upgrade \
--name v2-upgrade \
--version v2.0.0 \
--with-exportGenesis files saved to:
~/.devnet-builder/exports/<export-name>/genesis-<height>-<commit>.json(pre-upgrade)~/.devnet-builder/exports/<export-name>/genesis-<height>-<commit>.json(post-upgrade)
For rapid testing iterations, bypass the governance process entirely:
# Direct binary replacement without governance proposal
devnet-builder upgrade \
--name v2-upgrade \
--version v2.0.0 \
--skip-govThis will:
- Stop all nodes immediately
- Replace binary/image
- Restart nodes with new version
Use cases:
- Rapid iteration during development
- Testing binary compatibility
- Debugging upgrade migration code
Note: --skip-gov does not test the governance upgrade mechanism itself.
If an upgrade is interrupted (network issue, crash, etc.), you can resume:
# View current upgrade state
devnet-builder upgrade --show-status# Continue from where it stopped
devnet-builder upgrade --resumeIf upgrade state is corrupted:
# Clear upgrade state and start fresh
devnet-builder upgrade --clear-state
# Or force restart the upgrade
devnet-builder upgrade \
--name v2-upgrade \
--version v2.0.0 \
--force-restartThe upgrade process goes through these stages:
- Pending - Initial state
- Proposing - Submitting governance proposal
- Voting - Waiting for votes
- Waiting - Waiting for upgrade height
- Halted - Chain halted at upgrade height
- Switching - Replacing binary/image
- Restarting - Starting nodes with new version
- Verifying - Confirming chain resumed
- Completed - Upgrade successful
Export validator and account keys for testing.
# Export all keys (validators + accounts)
devnet-builder export-keysOutput:
Validators:
node0: <prefix>1abc...
Private Key: 0x1234...
node1: <prefix>1def...
Private Key: 0x5678...
Accounts:
account0: <prefix>1ghi...
Private Key: 0xabcd...
# JSON format for scripting
devnet-builder export-keys --json > keys.json
# Parse with jq
cat keys.json | jq '.validators[0].private_key'# Only validator keys
devnet-builder export-keys --type validators
# Only account keys
devnet-builder export-keys --type accounts# Get first account private key
PRIVATE_KEY=$(devnet-builder export-keys --json | jq -r '.accounts[0].private_key')
# Use with cast
cast send \
--rpc-url http://localhost:8545 \
--private-key $PRIVATE_KEY \
0xRecipientAddress \
--value 1etherconst keys = require('./keys.json');
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider('http://localhost:8545');
const wallet = new ethers.Wallet(keys.accounts[0].private_key, provider);
// Now use wallet for transactionsReset chain state while preserving configuration.
Reset chain data but keep keys and configuration:
# Stop nodes
devnet-builder stop
# Reset state
devnet-builder reset
# Restart
devnet-builder startThis preserves:
- Validator keys
- Account keys
- config.toml settings
- Genesis file
Reset everything including configuration:
# Full reset
devnet-builder reset --hard --force
# Redeploy
devnet-builder deployWhen you need a completely fresh start:
# Destroy everything
devnet-builder destroy --force
# Fresh deployment
devnet-builder deployTo reset a specific node:
# Stop the node
devnet-builder node stop node2
# Clear node data manually
rm -rf ~/.devnet-builder/devnet/node2/data/*
# Restart node
devnet-builder node start node2Note: The node will sync from other validators.
Choose the right execution mode for your use case.
Best for:
- Quick setup
- Consistent environment
- No local Go installation needed
- Testing with official releases
# Deploy with Docker (default)
devnet-builder deploy --mode docker
# Use specific image
devnet-builder deploy --mode docker --image 1.1.3-mainnetAdvantages:
- Pre-built images, fast startup
- Isolated from host system
- Easy cleanup
- Reproducible across machines
Best for:
- Testing local code changes
- Debugging with local tools
- Performance-critical testing
- Custom binary testing
# Deploy with local binaries
devnet-builder deploy --mode local
# Use specific binary
devnet-builder deploy --mode local --binary-ref /path/to/<binary-name>Requirements:
- Go 1.23+ installed
- Docker (for building)
- Build dependencies
You can switch modes for an existing devnet:
# Started with Docker
devnet-builder deploy --mode docker
# Stop nodes
devnet-builder stop
# Restart with local binary (for debugging)
devnet-builder start --mode local --binary-ref /path/to/debug-<binary-name>| Aspect | Docker ExecutionMode | Local ExecutionMode |
|---|---|---|
| Setup Time | Fast | Requires Go setup |
| Binary Source | Pre-built images | Built from source |
| Debugging | Container logs | Native tools (delve, etc.) |
| Performance | Good | Better (no container overhead) |
| Isolation | Full container | Shared host |
| Upgrades | Switch images | Build/cache binaries |
Use both modes for different phases:
# Initial testing with Docker (fast)
devnet-builder deploy --mode docker
# Run tests...
# Deep debugging with local binary
devnet-builder destroy --force
devnet-builder deploy --mode local
# Final validation with Docker (production-like)
devnet-builder destroy --force
devnet-builder deploy --mode dockerThe dvb CLI provides a kubectl-style interface for managing devnets through the daemon.
# Start the daemon
devnetd
# Or with custom socket
devnetd --socket /tmp/devnetd.sock# Apply a devnet configuration
dvb apply -f devnet.yaml
# List devnets
dvb get devnets
# Get detailed status
dvb describe devnet my-devnet
# Delete a devnet
dvb delete devnet my-devnet# Create an upgrade
dvb upgrade create v2-upgrade \
--devnet my-devnet \
--upgrade-name v2-upgrade \
--version v2.0.0
# List upgrades
dvb upgrade list
# Check upgrade status
dvb upgrade status v2-upgrade
# Cancel an upgrade
dvb upgrade cancel v2-upgrade
# Retry a failed upgrade
dvb upgrade retry v2-upgrade# Work in a specific namespace
dvb apply -f devnet.yaml -n team-alpha
# List devnets in namespace
dvb get devnets -n team-alpha
# List all devnets across namespaces
dvb get devnets --all-namespaces# Quick status
devnet-builder status
# Detailed node info
curl -s http://localhost:26657/status | jq
# Check peers
curl -s http://localhost:26657/net_info | jq '.result.n_peers'# Consensus state
curl -s http://localhost:26657/consensus_state | jq
# Validators
curl -s http://localhost:26657/validators | jq '.result.validators[].address'# Block number
curl -s http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
| jq -r '.result'
# Chain ID
curl -s http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
| jq -r '.result'# Recent errors
devnet-builder logs --tail 100 | grep -i error
# Follow logs for specific node
devnet-builder logs node0 -f- Command Reference - Complete CLI documentation
- Configuration - config.toml options
- Troubleshooting - Common issues and solutions