Debugging Solana Programs
There are a number of options and supporting tools for testing and debugging a Solana program.
Facts
Fact Sheet
- The crate
solana-program-test
enables use of bare bones local runtime where you can test and debug your program interactively (e.g. in vscode). - The crate
solana-validator
enables use of thesolana-test-validator
implementation for more robust testing that occurs on a local validator node. You can run from the editor but breakpoints in the program are ignored. - The CLI tool
solana-test-validator
runs and loads your program and processes transaction execution from command line Rust applications or Javascript/Typescript applications using web3. - For all the above, liberal use of
msg!
macro in your program is recommended at the start and then removing them as you test and ensure rock solid behavior. Remember thatmsg!
consumes Compute Units which can eventually fail your program by hitting the Compute Unit budget caps.
The steps in the following sections use the solana-program-bpf-template. Clone that to your machine:
git clone git@github.com:mvines/solana-bpf-program-template.git
cd solana-bpf-program-template
code .
Runtime Testing and Debugging in editor
Open the file src/lib.rs
You'll see that the program is a pretty simple and basically just logs the content received by the program entrypoint function: process_instruction
- Go to the
#[cfg(test)]
section and clickRun Tests
. This will build the program and then execute theasync fn test_transaction()
test. You will see the log messages (simplified) in the vscode terminal below the source.
running 1 test
"bpf_program_template" program loaded as native code
Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM invoke [1]
Program log: process_instruction: 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM: 1 accounts, data=[1, 2, 3]
Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM success
test test::test_transaction ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.41s
- Set a breakpoint on the programs
msg!
line (11) - Back in the test module, click
Debug
and within seconds the debugger will stop on the breakpoint and now you can examine data, step through functions, etc., etc..
These tests are also run from the command line with: cargo test
or cargo test-bpf
. Of course any breakpoints will be ignored.
How groovy can you get!
Note
Keep in mind you are not using a validator node so default programs, blockhashes, etc. are not represented or will not behave as they would when running in validator node. This is why the gang at Solana gave us Local Validator Node testing!
Local Validator Node Testing in editor
Integration testing using programmatic loading of a local validator node is defined in the tests/integration.rs
file.
By default, the template repo integration tests will only be runnable from the command line using cargo test-bpf
. The following steps will enable you to run within the editor as well as displaying program validator logs and msg!
outputs from your program:
- In the repo directory run
cargo build-bpf
to build the sample program - In the editor, open
tests/integration.rs
- Comment out line 1 ->
// #![cfg(feature = "test-bpf")]
- On line 19 change it to read:
.add_program("target/deploy/bpf_program_template", program_id)
- Insert the following at line 22
solana_logger::setup_with_default("solana_runtime::message=debug");
- Click
Run Test
above thetest_validator_transaction()
function
This will load the validator node then allowing you to construct a transaction (the Rust way) and submit to the node using the RcpClient
.
The program's output will also print out in the editor terminal. For example (simplified):
running 1 test
Waiting for fees to stabilize 1...
Waiting for fees to stabilize 2...
Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM invoke [1]
Program log: process_instruction: 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM: 1 accounts, data=[1, 2, 3]
Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM consumed 13027 of 200000 compute units
Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM success
test test_validator_transaction ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.40s
Debugging here will allow you to debug the functions and methods used in the test body but will not breakpoint in your program.
The bee's knees eh?
Local Validator Node Testing from Client Apps
Lastly, you can start a local validating node and load your program and any accounts using the solana-test-validator
from the command line.
In this approach, you will need a client application either using Rust RcpClient or in JavaScript or Typescript clients
See solana-test-validator --help
for more details and options. For the example program here is vanilla setup:
- Open a terminal in the repo folder
- Run
solana config set -ul
to set the configuration to point to local - Run
solana-test-validator --bpf-program target/deploy/bpf_program_template-keypair.json target/deploy/bpf_program_template.so
- Open another terminal and run
solana logs
to start the log streamer - You can then run your client program and observe program output in the terminal where you started the log streamer
Now that is the cat's pajamas YO!