Skip to main content
Version: master

leo devnode

A devnode is a lightweight-node network that bypasses the consensus algorithm and the requirement to generate proofs for deployment and execution transactions. It is a development tool intended for rapidly iterating on Aleo program design and running end-to-end tests prior to deploying Aleo programs to Testnet and Mainnet.

note

leo devnode is the recommended local development tool for lightweight testing. The older leo devnet command (which requires a full snarkOS installation and spins up a multi-validator network) remains available for more complex testing scenarios.

To initialize a devnode, run the following command:

leo devnode start --private-key <PRIVATE_KEY>
info

The default endpoint for a local devnode is http://localhost:3030.

Press Ctrl+C to stop the devnode. If started with --storage, the ledger state is saved and can be resumed by running the same command again. If started without --storage, the ledger is discarded when the devnode exits.

leo devnode start

leo devnode start [OPTIONS]
FlagShortDefaultDescription
--private-keyPrivate key (required, or set via PRIVATE_KEY environment variable)
--verbosity-v2Log verbosity level (02)
--socket-addr-a127.0.0.1:3030Address and port for the REST API
--genesis-path-g(built-in)Path to a custom genesis block file
--manual-block-creation-mfalseDisable automatic block creation after broadcast
--storage-s(in-memory)Directory for persistent ledger storage. If -s is given without a path, defaults to ./devnode/
--clear-storage-cfalseClear the ledger directory before starting. Requires --storage

Examples

# In-memory (ephemeral, no persistence)
leo devnode start --private-key APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH

# Persistent, default directory (./devnode/)
leo devnode start -s

# Persistent, custom directory
leo devnode start -s ./my-ledger

# Fresh start — wipe existing ledger before starting
leo devnode start -s -c
leo devnode start -s ./my-ledger -c

# Manual block creation (blocks only advance when explicitly requested)
leo devnode start --private-key APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH -m

leo devnode advance

Manually advances the ledger by creating new blocks. Useful when running with --manual-block-creation.

leo devnode advance [NUM_BLOCKS] [OPTIONS]
Argument / FlagDefaultDescription
NUM_BLOCKS1Number of blocks to create
--socket-addr127.0.0.1:3030Address of the running devnode

Examples

# Advance by 1 block
leo devnode advance

# Advance by 10 blocks
leo devnode advance 10

# Advance a devnode running on a non-default address
leo devnode advance 5 --socket-addr 127.0.0.1:4040

Skipping Proof Generation

When targeting a devnode, two proof-generation steps can be skipped for faster iteration. Proofs are not verified by the devnode, so generating them is unnecessary overhead.

Deploying a Program

leo deploy --skip-deploy-certificate --endpoint http://localhost:3030

--skip-deploy-certificate skips generating the deployment proof. Without it, deployment will still work but will be significantly slower.

Executing a Transition

leo execute <TRANSITION> <INPUTS> --skip-execute-proof --endpoint http://localhost:3030

--skip-execute-proof skips generating the execution proof. Without it, execution will still work but will be significantly slower.

Upgrading a Program

leo upgrade --skip-deploy-certificate --endpoint http://localhost:3030

Evaluating View Functions

A devnode exposes two REST endpoints for evaluating a program's view fn against the current ledger state. View functions are read-only: they compute a result from on-chain state without producing a transaction, so no key, signature, or proof is required.

Both endpoints are mounted under the network prefix (e.g. testnet) and are also available behind the v1 and v2 API version prefixes:

MethodPathDescription
POST/{network}/program/{id}/view/{function}Evaluate a view function at the latest block height.
POST/{network}/program/{id}/view/{function}/{height}Evaluate a view function at a specific block height.

The request body is a JSON array of the view function's inputs, each encoded as an Aleo value string. Pass [] when the function takes no inputs. The response is a JSON array of the function's outputs.

The latest-height endpoint accepts an optional ?metadata=true query parameter; when set, the response is wrapped as { "data": [...], "height": <block_height> } instead of a bare output array.

Examples

# Evaluate `my_view` on `my_program.aleo` at the latest height
curl -X POST http://localhost:3030/testnet/program/my_program.aleo/view/my_view \
-H 'Content-Type: application/json' \
-d '["1u32", "2u32"]'

# Include the block height the result was evaluated at
curl -X POST 'http://localhost:3030/testnet/program/my_program.aleo/view/my_view?metadata=true' \
-H 'Content-Type: application/json' \
-d '[]'

# Evaluate against historical state at block height 10
curl -X POST http://localhost:3030/testnet/program/my_program.aleo/view/my_view/10 \
-H 'Content-Type: application/json' \
-d '[]'

Under the v2 prefix the endpoints return 422 Unprocessable Entity for malformed inputs and 400 Bad Request for an unknown view function or a height before the program was deployed.

Typical Workflow

# 1. Start a persistent devnode
leo devnode start --private-key APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH -s

# 2. Deploy your program (in another terminal, from your Leo project directory)
leo deploy --skip-deploy-certificate --endpoint http://localhost:3030

# 3. Execute a transition
leo execute <TRANSITION> <INPUTS> --skip-execute-proof --endpoint http://localhost:3030

# 4. Reset and start fresh when needed
leo devnode start --private-key APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH -s -c