Glassbox is a premium developer toolset for the Stellar network, designed to provide high-fidelity "glass-box" debugging and simulation for Soroban smart contracts.
Status: Active Development (Phase 4: Advanced Diagnostics) Documentation: https://dotandev-glassbox-75.mintlify.app/ Focus: High-Fidelity Simulation, Auth Tracing, and Security Auditing
The primary goal of Glassbox is to eliminate the opaque "black box" experience of failed Stellar smart contract transactions. By providing local-first, high-fidelity replay and tracing, Glassbox maps generic network errors back to human-readable diagnostic events and source code.
Core Features (Planned):
- Transaction Replay: Fetch a failed transaction's envelope and ledger state from an RPC provider.
- Local Simulation: Re-execute the transaction logically in a local environment.
- Trace decoding: Map execution steps and failures back to readable instructions or Rust source lines.
- Source Mapping: Map WASM instruction failures to specific Rust source code lines using debug symbols.
- GitHub Source Links: Automatically generate clickable GitHub links to source code locations in traces (when in a Git repository).
- Error Suggestions: Heuristic-based engine that suggests potential fixes for common Soroban errors.
Fetches a transaction envelope from the Stellar network and simulates it locally.
# Debug on mainnet (network is auto-detected when the flag is omitted)
glassbox debug <transaction-hash>
# Debug explicitly on testnet
glassbox debug --network testnet <transaction-hash>
# Debug with a custom RPC endpoint
glassbox debug --network testnet --rpc-url https://soroban-testnet.stellar.org <transaction-hash>Debug an offline envelope from a local XDR file (no RPC required):
glassbox debug --xdr-file tx.xdrOr from a JSON envelope file:
glassbox debug --json-file tx.jsonExpected output:
Debugging transaction: 5c0a...
Network: testnet
Transaction fetched successfully. Envelope size: 312 bytes
────────────────────────────────────────────────────────────
Result for testnet
✓ Status: success
ℹ Snapshot: complete
── Resource Usage
CPU Instructions: 12345 / 100000000 (0.01%)
Memory Bytes: 1024 / 41943040 (0.00%)
Operations: 1
Session created: sess_abc123
Run 'glassbox session save' to persist this session.
Test a contract locally without any network connection:
glassbox debug --wasm ./target/wasm32-unknown-unknown/release/my_contract.wasmPass mock arguments:
glassbox debug --wasm ./contract.wasm --args "arg1" --args "arg2"Enable hot-reload to automatically re-run when the WASM binary changes:
glassbox debug --wasm ./contract.wasm --hot-reloadPrint sample output to test color detection without any network or WASM:
glassbox debug --demoGenerate interactive flamegraphs to visualize CPU and memory consumption during contract execution.
The --profile flag is a global (root-level) flag:
glassbox --profile debug <transaction-hash>Export format options:
# Interactive HTML (default)
glassbox --profile --profile-format html debug <transaction-hash>
# Raw SVG
glassbox --profile --profile-format svg debug <transaction-hash>The flamegraph is written to <tx-hash-prefix>.flamegraph.html (or .svg) in the current directory.
See docs/trace-profiling.md for detailed documentation and docs/examples/sample_flamegraph.html for a live demo.
Validate all inputs and check the environment without running a simulation:
glassbox debug --dry-run --network testnet <transaction-hash>This checks the transaction hash format, network validity, RPC reachability, simulator binary presence, and protocol version — no simulation is executed.
Run the same transaction through two networks and diff the results:
glassbox debug --network testnet --compare-network mainnet <transaction-hash>Poll for a pending transaction and debug it once it lands on-chain:
glassbox debug --watch --watch-timeout 60 --network testnet <transaction-hash>Save ledger state during a debug run for later offline replay:
# Save snapshot registry while debugging
glassbox debug --save-snapshots ./snapshots/my-tx.json --network testnet <transaction-hash>
# Replay later without any network connection
glassbox debug --load-snapshots ./snapshots/my-tx.jsonGlassbox can generate a deterministic, signed audit log from a JSON payload.
Provide a PKCS#8 PEM Ed25519 private key via environment variable or flag:
- Env:
GLASSBOX_AUDIT_PRIVATE_KEY_PEM - Flag:
--software-private-key <pem-or-path>
Example:
glassbox audit:sign \
--payload '{"input":{},"state":{},"events":[],"timestamp":"2026-01-01T00:00:00.000Z"}' \
--software-private-key "$(cat ./ed25519-private-key.pem)"Read the payload from a file:
glassbox audit:sign --payload-file payload.json \
--software-private-key ./ed25519-private-key.pemSelect the PKCS#11 provider with --signing-provider pkcs11 and configure the module,
token, and key via flags or environment variables.
Required:
--pkcs11-module/GLASSBOX_PKCS11_MODULE— path to the PKCS#11.so/.dylib/.dll--pkcs11-pin/GLASSBOX_PKCS11_PIN— user PIN--pkcs11-key-label/GLASSBOX_PKCS11_KEY_LABELor--pkcs11-key-id/GLASSBOX_PKCS11_KEY_ID(hex)
Optional:
GLASSBOX_PKCS11_SLOT— numeric slot index (default0; must be a non-negative integer)GLASSBOX_PKCS11_TOKEN_LABEL— select token by labelGLASSBOX_PKCS11_PUBLIC_KEY_PEM— SPKI PEM public key embedded in the signed audit log
The PKCS#11 signer keeps the module, session, and key handle alive for the lifetime of the signer instance. Stale sessions are retried once automatically before returning an error.
Example:
export GLASSBOX_PKCS11_MODULE=/usr/lib/softhsm/libsofthsm2.so
export GLASSBOX_PKCS11_PIN=1234
export GLASSBOX_PKCS11_KEY_LABEL=glassbox-audit-key
glassbox audit:sign \
--signing-provider pkcs11 \
--payload '{"input":{},"state":{},"events":[],"timestamp":"2026-01-01T00:00:00.000Z"}'Run a preflight check before signing to surface configuration errors with actionable hints:
glassbox audit:sign --signing-provider pkcs11 --validate-only \
--pkcs11-module /usr/lib/softhsm/libsofthsm2.so --pkcs11-pin 1234This verifies module loading, slot enumeration, PIN authentication, key lookup, and a test signing operation — without touching any payload.
The command prints the signed audit log JSON to stdout so it can be redirected to a file.
For platform-specific module paths, YubiKey setup, and troubleshooting, see docs/audit-signing.md.
Glassbox registers a custom glassbox:// URI scheme, allowing external tools (browsers,
dashboards) to deep-link directly into a debug session.
Register the protocol handler:
glassbox protocol:registerPreview what registration would do without writing any OS state:
glassbox protocol:register --dry-runOpen a debug session via URI:
glassbox protocol:handle "glassbox://debug/<transaction-hash>?network=testnet"With an optional operation index and view mode:
glassbox protocol:handle "glassbox://debug/<transaction-hash>?network=mainnet&op=0&view=flamegraph"Verify the registration is working:
glassbox protocol:verifyDiagnose registration issues:
glassbox protocol:diagnoseRepair a broken registration:
glassbox protocol:repairCheck current registration status:
glassbox protocol:statusUnregister the handler when no longer needed:
glassbox protocol:unregister# Debug a transaction and save the session
glassbox debug --network testnet <transaction-hash>
glassbox session save
# Save with a name for easy reference
glassbox session save --name payroll-bug
# List all saved sessions
glassbox session list
# Resume a session
glassbox session resume <session-id>
# Delete a session
glassbox session delete <session-id>
# Recover a session left by a crashed process
glassbox session recover
# Check sessions for schema and integrity problems
glassbox session doctor# Check cache usage
glassbox cache status
# Include RPC cache statistics
glassbox cache status --rpc
# Clean old entries (LRU)
glassbox cache clean
# Clean without confirmation prompt
glassbox cache clean --force
# Remove RPC cache entries older than 7 days
glassbox cache rpc --older-than 7
# Remove all testnet RPC cache entries
glassbox cache rpc --network testnet
# Clear all cached data
glassbox cache clear --force# Show current telemetry state and how to disable it
glassbox telemetryTelemetry is opt-in only and is disabled by default. To opt in, set telemetry_enabled = true
in ~/.Glassbox/config.json or run with --telemetry. To disable for the current shell session:
export GLASSBOX_TELEMETRY=falseNo secrets are exported — transaction hashes, contract IDs, and file paths are sanitized client-side before any data leaves the machine.
# Human-readable output
glassbox version
# Machine-readable JSON
glassbox version --json- Observability Troubleshooting: Practical guide to logs, Prometheus metrics, OpenTelemetry traces, telemetry events, correlation IDs, and collection failure diagnosis.
- Source Mapping: Implementation details for mapping WASM failures to Rust source code.
- JSON CLI Output: Machine-readable
--json/--format jsonoptions for automation. - Audit Log Signing: Software and HSM signing for audit logs.
- Audit KMS Signing: AWS KMS signing integration.
- Canonicalization: Deterministic JSON serialization for audit log hashing.
- Trace Profiling: CPU/memory flamegraph generation from contract traces.
- Trace Export Validation: Validated
--trace-outputand format options. - Incremental Trace Refresh: Incremental trace viewer state persistence.
- Snapshot Deduplication: How ledger snapshots are deduplicated.
- Binding Validation: ABI binding generation and validation.
- Runtime Binding Validation: Runtime validators for command inputs, trace payloads, audit records, and session envelopes.
- Sandboxed Replay: Isolated WASM replay in a sandboxed environment.
- Session Bookmarking: Persistent session management and bookmarks.
- Security Warnings: Deprecated host functions and security findings.
- Telemetry Metadata: What telemetry data is collected and how.
- Telemetry Sampling: Sampling strategy for telemetry events.
- Watch Mode:
--watchand--watch-filespolling modes. - Regression Test Guide: How to write structured regression tests.
- Interactive Trace Showcase: Try out the interactive trace explorer online.
Stellar's soroban-env-host executes WASM. When it traps (crashes), the specific reason is often sanitized or lost in the XDR result to keep the ledger size small.
Glassbox operates by:
- Fetching Data: Using the Stellar RPC to get the
TransactionEnvelopeandLedgerFootprint(read/write set) for the block where the tx failed. - Simulation Environment: A Rust binary (
glassbox-sim) that integrates withsoroban-env-hostto replay transactions. - Execution: Feeding the inputs into the VM and capturing
diagnostic_events.
We are building this open-source to help the entire Stellar community. All contributions, from bug reports to new features, are welcome. Please follow our guidelines to ensure code quality and consistency.
- Go 1.24.0+
- Rust 1.70+ (for building the simulator binary)
- Stellar CLI (for comparing results)
make(for running standard development tasks)
-
Clone the repo:
git clone https://github.com/dotandev/glassbox.git cd glassbox -
Install dependencies:
go mod download cd simulator && cargo fetch && cd ..
-
Build the Rust simulator:
cd simulator cargo build --release cd ..
-
Run tests:
go test ./... cargo test --release -p glassbox-sim
This project enforces strict linting rules to maintain code quality. See docs/STRICT_LINTING.md for details.
Quick commands:
# Run all strict linting (Go + Rust)
make lint-all-strict
# Go linting only
make lint-strict
# Rust linting only
make rust-lint-strict
# Install pre-commit hooks
pip install pre-commit && pre-commit installThe CI pipeline fails immediately on:
- Unused variables, imports, or functions
- Dead code
- Any linting warnings
Glassbox includes optional telemetry to help diagnose runtime issues. Privacy-preserving defaults and explicit opt-in are enforced:
- Opt-in by default: Telemetry is disabled unless explicitly enabled via config or environment.
- Config options: Set
telemetry_enabledandtelemetry_endpointin your Glassbox config (~/.Glassbox/config.json), or use the environment variablesGLASSBOX_TELEMETRYandGLASSBOX_TELEMETRY_ENDPOINT. - No secrets: Identifiers such as transaction hashes, contract IDs, and file paths are sanitized or fingerprinted client-side before export.
- Session control: Run
glassbox telemetryto view the current state and follow the printed instructions to disable telemetry for your shell session.
If you have additional privacy concerns, file an issue and we will work with you to provide stricter controls.
- Formatting: Run
go fmt ./...before committing - Linting: Must pass
golangci-lintwithout errors:golangci-lint run ./...
- Naming Conventions:
- Use
PascalCasefor exported identifiers (types, functions, constants) - Use
camelCasefor unexported identifiers - Use
UPPER_SNAKE_CASEfor constants - Interface names should end with
-er:Reader,Writer,Logger
- Use
- Error Handling:
- Always check and handle errors explicitly
- Wrap errors with context using
fmt.Errorf:fmt.Errorf("operation failed: %w", err) - Never use bare
panic()in production code
- Documentation:
- All exported functions and types must have documentation comments
- Comments should be complete sentences starting with the name
- Example:
// Logger provides structured logging for diagnostic events.
- Formatting: Run
cargo fmt --allbefore committing - Linting: Must pass
cargo clippy:cargo clippy --all-targets --release -- -D warnings
- Naming Conventions:
- Use
snake_casefor functions and variables - Use
PascalCasefor types and traits - Use
UPPER_SNAKE_CASEfor constants
- Use
- Error Handling:
- Prefer
Result<T, E>over panics - Use custom error types for domain-specific errors
- Avoid unwrapping in production code except for obvious invariants
- Prefer
- Documentation:
- Document all public functions with doc comments (
///) - Include examples for complex functions
- Use
cargo doc --opento review generated documentation
- Document all public functions with doc comments (
Follow the Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: A new featurefix: A bug fixtest: Adding or improving testsdocs: Documentation changesrefactor: Code refactoring without feature changesperf: Performance improvementschore: Build, CI, or dependency updatesci: CI/CD configuration changes
Scopes: Use specific areas like sim, cli, updater, trace, analyzer, etc.
Examples:
feat(sim): Add protocol version spoofing for harness
test(sim): Add 1000+ transaction regression suite
fix(updater): Handle network timeouts gracefully
docs: Add comprehensive contribution guidelines
Rules:
- Keep subject line under 50 characters
- Use imperative mood ("add", not "added" or "adds")
- No period at the end of the subject
- Provide detailed explanation in the body if the change is non-obvious
- Reference related issues:
Closes #350, refs #343
- Title: Follow commit message convention (this becomes the squashed commit)
- Description:
- Brief summary of changes
- Link to related issues:
Closes #XXX - Explain the "why" behind the changes
- Highlight any breaking changes
- PR Checks:
- All CI checks must pass
- Code coverage must not decrease
- All tests must pass locally before submitting
- Format:
## Description Brief explanation of the changes. ## Related Issues Closes #350, relates to #343 ## Testing How was this tested? Include specific test cases. ## Checklist - [ ] Code follows style guidelines - [ ] Tests added/updated - [ ] Documentation updated - [ ] No new warnings or errors
- Unit Tests: All new functions must have unit tests
- Coverage: Aim for 80%+ coverage. Critical paths should have 90%+ coverage
- Integration Tests: Include tests that verify feature interactions
- Regression Tests: See docs/regression-test-guide.md for the structured regression template
- Running Tests:
# Go tests go test -v -race ./... go test -v -race -cover ./... # Rust tests cargo test --all cargo test --all --release
- Bench Tests: For performance-critical code, include benchmarks:
go test -bench=. -benchmem ./...
-
Create a branch:
git checkout -b feat/my-feature # or for bug fixes: git checkout -b fix/issue-description -
Make changes and test locally:
go test ./... go fmt ./... golangci-lint run ./... cargo clippy --all-targets -- -D warnings cargo fmt --all -
Commit with conventional messages:
git add . git commit -m "feat(scope): description"
-
Push and create PR:
git push origin feat/my-feature # Then create PR on GitHub with detailed description -
Address feedback:
- Make requested changes
- Commit with descriptive messages
Run the provided scripts before submitting:
# Format Go code
go fmt ./...
# Run linters
golangci-lint run ./...
# Format Rust code
cargo fmt --all
# Check Rust with clippy
cargo clippy --all-targets --release -- -D warnings
# Run all checks
make lint
make formatA script is provided to verify that all command invocations in the README match the actual CLI surface:
scripts/check-readme-commands.shRun it before submitting a PR that touches README.md or any internal/cmd/*.go file.
It exits non-zero and prints each unknown command reference if any are found.
To prevent regressions in artifact sizes, Glassbox tracks the compiled sizes of both the Go CLI and Rust simulator.
- Configuring Thresholds: Adjust maximum size thresholds (in bytes) inside the
size_thresholds.conffile at the root of the repository. - Local Checks: After building, run
make size-checkto measure your artifacts against the configured limits. - CI Pipeline: Size checks automatically run on all Pull Requests and pushes to
mainordevelopvia thesize-check.ymlGitHub workflow. Builds will fail if size thresholds are exceeded.
See docs/proposal.md for the detailed proposal.
- Phase 1: Research RPC endpoints for fetching historical ledger keys.
- Phase 2: Build a basic "Replay Harness" that can execute a loaded WASM file.
- Phase 3: Connect the harness to live mainnet data.
- Phase 4: Advanced Diagnostics & Source Mapping (Current Focus).
go test -run TestName ./package/...go test -cpuprofile=cpu.prof -memprofile=mem.prof ./...
go tool pprof cpu.profGOOS=linux GOARCH=amd64 go build -o glassbox-linux-amd64 ./cmd/glassboxgo clean
cargo clean
make cleanWhen reviewing PRs, ensure:
- Code follows naming and style conventions
- Error handling is appropriate
- Tests are adequate and pass
- Documentation is clear and complete
- No unnecessary dependencies added
- Performance implications considered
- Security implications reviewed
- Commit messages follow convention
- Questions? Open a GitHub Discussion
- Found a bug? Create an Issue with reproduction steps
- Have an idea? Start a Discussion before implementing
- Documentation issue? Create an Issue with details
- No Emojis: Commit messages and PR titles should not contain emojis
- No "Slops": Avoid vague language like "fixes stuff" or "updates things"
- Clear Messages: Every commit should have a clear, descriptive message
- Lint-Free: Only suppress linting errors if they are objectively false positives. Always explain suppression with
// nolint:rule-namecomments - Assume Bad Faith in Code: Write code defensively, validate inputs, handle edge cases
Thanks goes to these wonderful people:
dotdev. Code Documentation Ideas & Planning |
This project follows the all-contributors specification. Contributions of any kind welcome!
Glassbox is an open-source initiative. Contributions, PRs, and Issues are welcome.