canopy-network/canopy
The official go implementation of the Canopy Network protocol
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1w ago
- ✓5 active contributors
- ✓Distributed ownership (top contributor 42% of recent commits)
Show all 6 evidence items →Show less
- ✓MIT licensed
- ✓CI configured
- ⚠No test directory detected
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/canopy-network/canopy)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/canopy-network/canopy on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: canopy-network/canopy
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/canopy-network/canopy shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 1w ago
- 5 active contributors
- Distributed ownership (top contributor 42% of recent commits)
- MIT licensed
- CI configured
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live canopy-network/canopy
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/canopy-network/canopy.
What it runs against: a local clone of canopy-network/canopy — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in canopy-network/canopy | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 39 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of canopy-network/canopy. If you don't
# have one yet, run these first:
#
# git clone https://github.com/canopy-network/canopy.git
# cd canopy
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of canopy-network/canopy and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "canopy-network/canopy(\\.git)?\\b" \\
&& ok "origin remote is canopy-network/canopy" \\
|| miss "origin remote is not canopy-network/canopy (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "cmd/main/main.go" \\
&& ok "cmd/main/main.go" \\
|| miss "missing critical file: cmd/main/main.go"
test -f "bft/bft.go" \\
&& ok "bft/bft.go" \\
|| miss "missing critical file: bft/bft.go"
test -f "cmd/rpc/server.go" \\
&& ok "cmd/rpc/server.go" \\
|| miss "missing critical file: cmd/rpc/server.go"
test -f "cmd/rpc/web/explorer" \\
&& ok "cmd/rpc/web/explorer" \\
|| miss "missing critical file: cmd/rpc/web/explorer"
test -f "bft/msg.go" \\
&& ok "bft/msg.go" \\
|| miss "missing critical file: bft/msg.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 39 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~9d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/canopy-network/canopy"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Canopy is the official Go implementation of the Canopy Network Protocol, a recursive blockchain framework where chains bootstrap each other into independence. It provides a peer-to-peer launchpad for launching new sovereign blockchains secured by a Byzantine Fault Tolerant consensus mechanism, with built-in persistence, state machine logic, and decentralized networking. Monorepo structure: Go implementation in root with core modules (bft/bft.go, fsm/, p2p/, store/, controller/) handling consensus, state transitions, networking, and persistence; .docker/ contains multi-node Betanet setup with 3 validator nodes (volumes/node_1/2/3/) pre-configured; separate explorer UI as a Next.js/React TypeScript app using Vite; plugins for C#, Kotlin, Python, TypeScript via auto-update Dockerfiles.
👥Who it's for
Blockchain developers and network operators who want to launch new sovereign chains using Canopy's recursive framework; protocol contributors implementing BFT consensus, P2P networking, or state machine logic; and validators running Canopy nodes on Betanet.
🌱Maturity & risk
Canopy is actively developed but pre-production: it's in Betanet with a published roadmap to mainnet, has comprehensive CI/CD via GitHub Actions (.github/workflows/), Docker Compose support for multi-node testing (.docker/compose.yaml), and a structured codebase with core modules (controller, fsm, bft, p2p, store). However, as alphanet/betanet software, it carries higher risk than production systems.
Primary risks: (1) Betanet status means protocol and APIs may change; (2) complex consensus and cryptography code (bft/, fsm/) requires careful auditing; (3) dependency on Go 1.21+ and specific Next.js 14.2.3 for explorer frontend could create version conflicts; (4) limited visibility into test coverage and active issue backlog from the file list alone.
Active areas of work
The project is preparing for mainnet launch with active Betanet operations; multiple language SDK releases (release-plugin-*.yml workflows); Docker auto-update infrastructure for language bindings; and structured issue/PR templates indicating organized development governance.
🚀Get running
Clone, build, and run locally:
git clone https://github.com/canopy-network/canopy.git
cd canopy
make build/canopy-full
canopy start
Or with Docker Compose:
docker-compose -f .docker/compose.yaml up
Daily commands: Development server:
make build/canopy-full
canopy start
With Docker:
docker-compose -f .docker/compose.yaml up
Explorer (TypeScript/React):
cd explorer # if separate directory
npm install
npm run dev # runs Vite dev server
🗺️Map of the codebase
cmd/main/main.go— Entry point for the Canopy Network node; initializes the BFT consensus engine and RPC serverbft/bft.go— Core Byzantine Fault Tolerant consensus implementation; foundation for block validation and finalitycmd/rpc/server.go— RPC server routing and handler setup; exposes blockchain queries and admin endpointscmd/rpc/web/explorer— Web UI for blockchain exploration; primary user-facing interface for chain inspectionbft/msg.go— Message protocol definitions for BFT consensus rounds; critical for peer-to-peer communication.docker/compose.yaml— Local testnet orchestration; defines multi-node setup for consensus testing and development
🛠️How to make changes
Add a New RPC Query Endpoint
- Define the query handler function in cmd/rpc/query.go following existing pattern (e.g., QueryBalance, QueryHeight) (
cmd/rpc/query.go) - Register the route in cmd/rpc/routes.go using router.HandleFunc() with HTTP method and path (
cmd/rpc/routes.go) - Define request/response structs in cmd/rpc/types.go (
cmd/rpc/types.go) - Test the endpoint by calling it via CLI (cmd/cli/query.go) or curl against localhost:8080
Add a New BFT Consensus Message Type
- Define the protobuf message in bft/bft.pb.go or related .proto source (regenerate with protoc if needed) (
bft/bft.pb.go) - Add handling logic in bft/msg.go's message dispatcher based on message type discriminator (
bft/msg.go) - Implement validation in bft/bft.go's consensus state machine (Handle* methods) (
bft/bft.go) - Write unit tests in bft/msg_test.go following existing test patterns (marshalling, validation) (
bft/msg_test.go) - Test end-to-end with local testnet using docker compose: cd .docker && docker-compose up (
.docker/compose.yaml)
Add a New Web Explorer Dashboard Tab
- Create a new React component in cmd/rpc/web/explorer/src/components/ following existing tab patterns (
cmd/rpc/web/explorer/package.json) - Use @tanstack/react-query hooks to fetch data from RPC endpoints (/api/query/* or /api/admin/*) (
cmd/rpc/web/explorer/package.json) - Style with Tailwind CSS utilities (cmd/rpc/web/explorer/postcss.config.js included) (
cmd/rpc/web/explorer/postcss.config.js) - Register the tab route in main app router (cmd/rpc/web/explorer/index.html or routing config) (
cmd/rpc/web/explorer/index.html) - Run dev server: npm run dev in cmd/rpc/web/explorer/, build with npm run build (
cmd/rpc/web/explorer/package.json)
Configure a New Testnet Node
- Copy node configuration template from .docker/volumes/node_1/config.json to new directory (
.docker/volumes/node_1/config.json) - Set unique node ID, P2P port, RPC port, and peer addresses in config.json (
.docker/volumes/node_1/config.json) - Generate or copy validator key and keystore (validator_key.json, keystore.json) from genesis setup (
.docker/volumes/node_1/validator_key.json) - Add service definition to .docker/compose.yaml with volume mounts and network aliases (
.docker/compose.yaml) - Run docker-compose up and check logs: docker-compose logs <service_name> (
.docker/compose.yaml)
🔧Why these technologies
- Go (golang v1.21) — High-performance consensus and networking; minimal resource footprint for validator nodes; statically-compiled single binary deployment
- Byzantine Fault Tolerance (BFT) Consensus — Provides finality and security guarantees; tolerates up to 1/3 malicious validators; decentralized block validation without external trust anchors
- React 19 + Vite — Modern UI framework for real-time blockchain explorer; fast HMR development experience; minimal build footprint for embedded web server
- Protobuf (bft.pb.go) — Efficient binary serialization for consensus messages; cross-language compatibility for multi-chain plugins
- Docker Compose — Reproducible multi-node testnet environment; simplifies CI/CD and local development validation across consensus rounds
⚖️Trade-offs already made
-
Embedded RPC server + web explorer vs. separate services
- Why: Single binary distribution; operators run node + UI in one process
- Consequence: Web UI updates coupled to node releases; UI performance affects node responsiveness if blocking; reduces operational complexity for small validators
-
Protobuf serialization for consensus vs. JSON
- Why: Bandwidth and latency optimization for rapid consensus rounds across global validators
- Consequence: Harder to debug live consensus traffic; requires code generation from .proto files; not human-readable in logs
-
React Query + React Router in explorer UI vs. Next.js
- Why: Lighter client-side SPA avoids server-side rendering overhead; explorer is read-heavy and interactive
- Consequence: No built-in static site generation; all rendering on client; initial bundle size larger but cacheable
-
Recursive architecture (chains bootstrap each other) vs. central relay
- Why: Reduces dependency on single trusted infrastructure; enables permissionless chain launches
- Consequence: More complex onboarding logic; requires peer discovery and genesis coordination across chains
🚫Non-goals (don't propose these)
- Not a general-purpose blockchain VM; focused on peer-to-peer chain coordination and consensus, not smart contract execution
- Does not implement proof-of-work or hybrid consensus; BFT-only for finality
- Web explorer is not a wallet or transaction signer; read-only chain queries and admin endpoints require separate authentication/signing
🪤Traps & gotchas
Config requirement: Running a node requires config.json, genesis.json, keystore.json, and validator_key.json in the node's volume — .docker/volumes/node_1/ shows the structure. Go version pin: Requires Go 1.21+ (from README badge); older versions will fail builds. Next.js/Vite version sensitivity: Explorer uses exact versions (Next.js 14.2.3, Vite 7.1.2); package.json lockfile critical. Consensus initialization: BFT requires genesis state and validator key setup before start (see node volumes); misconfigured genesis.json breaks consensus. Network ports: Docker Compose exposes specific node ports; port conflicts will prevent startup.
🏗️Architecture
💡Concepts to learn
- Byzantine Fault Tolerance (BFT) — Canopy's consensus mechanism (bft/ module) allows validators to reach agreement even when some nodes are faulty or malicious — this is the core safety guarantee for the chain
- Finality and Consensus Rounds — BFT consensus happens in rounds with voting stages; understanding proposal, prevote, precommit phases in bft.go is essential for debugging consensus hangs or forks
- Recursive Blockchain Bootstrap — Canopy's unique value proposition: chains bootstrap each other into independence using the same consensus engine; this recursive architecture requires understanding how genesis states and validators are delegated
- State Machine Validity and Transitions — The fsm/ module defines what transactions are valid and how they mutate state; incorrect state machine logic breaks the blockchain's integrity independent of consensus correctness
- Merkle Trees and State Proofs — Canopy's store/ module uses Merkle trees for state verification and transaction indexing; understanding Merkle roots and proofs is critical for debugging state verification failures
- P2P Peer Discovery and Encrypted Channels — The p2p/ module handles node-to-node communication with encryption; understanding peer gossip protocols, bootstrapping, and channel security is essential for networking issues
- Protobuf Message Serialization — All consensus and networking messages use Protocol Buffers (bft.pb.go); changing message formats requires regenerating .pb.go files and understanding wire format compatibility
🔗Related repos
cosmos/cosmos-sdk— Similar modular blockchain framework with consensus (Tendermint BFT), state machine, and P2P networking — reference for how production blockchains structure these componentsethereum/go-ethereum— Go blockchain implementation with similar persistence, networking, and consensus concerns; architectural patterns for ledger storage and validator management applicable to Canopytendermint/tendermint— Pure BFT consensus implementation that influenced Canopy's bft/ module; understand this to grasp why Canopy chose recursive architecture over single chaingrpc/grpc-go— Likely underlying RPC mechanism for Canopy's P2P networking and node communication; dependency for understanding message serialization in bft.pb.goprotocolbuffers/protobuf— Schema language for bft.pb.go (protobuf-generated consensus messages); understanding .proto definitions helps modify consensus message formats
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add CI workflow for explorer frontend build validation
The repo has multiple release workflows for plugins (Go, Python, TypeScript, etc.) but lacks a dedicated CI pipeline for the explorer frontend. The explorer package.json shows it uses TypeScript, Vite, and ESLint, but there's no GitHub Actions workflow to validate builds, run type-checks, or lint on PRs. This prevents catching regressions in the React/Vite setup early.
- [ ] Create .github/workflows/build-test-explorer.yml that runs on PR/push
- [ ] Add steps to run 'npm install', 'npm run type-check', 'npm run lint', and 'npm run build' in the explorer directory
- [ ] Configure the workflow to fail if any step fails, blocking merges of broken frontend code
- [ ] Test locally with 'npm run build' in the explorer directory to ensure the workflow matches actual build steps
Add comprehensive test coverage for BFT consensus module
The bft/ directory contains critical consensus logic (bft.go, election.go, evidence.go, vote.go, prop.go) with corresponding test files, but the test files appear minimal. The .md documentation files (bft.md, election.md, evidence.md, etc.) suggest complex state machine behavior. New contributors should expand test coverage for edge cases in Byzantine Fault Tolerance to ensure protocol safety.
- [ ] Review existing tests in bft/*_test.go files to identify coverage gaps (especially election rounds, vote validation, and evidence handling)
- [ ] Add tests for Byzantine scenarios: duplicate votes, conflicting proposals, and network partition recovery using the existing mock_test.go framework
- [ ] Add integration tests combining multiple BFT components (election + vote + evidence) to verify state transitions
- [ ] Run 'go test ./bft -cover' to measure coverage and target 80%+ for critical consensus paths
Add missing CI workflows for remaining language SDKs (C#, Kotlin, Python)
The repo has .github/workflows/ for Go and TypeScript plugin releases, but C#, Kotlin, and Python plugins in .docker/auto-update/ lack corresponding GitHub Actions workflows. The Dockerfiles exist (.docker/auto-update/Dockerfile.csharp, .kotlin, .python) but there's no automated build/test/release pipeline for these SDKs, creating maintenance burden and inconsistency with the Go/TypeScript setup.
- [ ] Create .github/workflows/release-plugin-csharp.yml (if not present) mirroring the structure of release-plugin-go.yml
- [ ] Create .github/workflows/release-plugin-kotlin.yml with appropriate build/test steps for Kotlin/JVM tooling
- [ ] Create .github/workflows/release-plugin-python.yml with tox or pytest integration for multiple Python versions
- [ ] Reference the .docker/auto-update/entrypoint.sh to understand build requirements for each language
🌿Good first issues
- Add missing test coverage for bft/ package: bft.pb.go exists (protobuf-generated) but test files are not visible in file list — write unit tests for key consensus functions to improve coverage and documentation
- Expand README.md for each core module: controller/README.md, fsm/README.md, bft/README.md exist but lack concrete code examples — add 'Getting Started' sections with code snippets showing how to integrate each module
- Improve Docker auto-update Dockerfiles: .docker/auto-update/Dockerfile.* for multiple languages exist but lack version pinning and security best practices — audit and add explicit base image SHA pins and security scanning
⭐Top contributors
Click to expand
Top contributors
- @andrewnguyen22 — 42 commits
- @rem1niscence — 30 commits
- @pablocampogo — 26 commits
- @purelualight — 1 commits
- @stringsbuilder — 1 commits
📝Recent commits
Click to expand
Recent commits
73685b8— Merge pull request #380 from purelualight/main (rem1niscence)efe6922— Merge pull request #387 from canopy-network/fix-keystore-wallet (rem1niscence)c520cfe— fix: make delete key ask for password and import pop up dissappear (pablocampogo)2ee6a54— Merge pull request #386 from canopy-network/fix-config-wallet-explorer (andrewnguyen22)a240113— Fix explorer pending status and order search (andrewnguyen22)f2c74a0— fix: delete link to explorer from wallet, fix staking view in wallet, add orders to global search in explorer and fix is (pablocampogo)d2e99bd— Merge pull request #379 from canopy-network/fix/p2p (rem1niscence)bc132b8— wallet: carry local UI and config fixes (andrewnguyen22)bc37087— Merge pull request #381 from canopy-network/fix-wallet-explorer (andrewnguyen22)c958da8— Merge origin/main into fix-wallet-explorer (andrewnguyen22)
🔒Security observations
- High · Hardcoded Secrets in Docker Volumes —
.docker/volumes/node_1/validator_key.json, .docker/volumes/node_2/validator_key.json, .docker/volumes/node_3/validator_key.json, and keystore.json files. The repository contains committed validator keys and keystore files in .docker/volumes/node_*/. These files (validator_key.json, keystore.json) likely contain sensitive cryptographic material that should never be committed to version control, even in test environments. Fix: Remove all sensitive key files from version control immediately. Add .docker/volumes to .gitignore. Generate keys at runtime or use secret management solutions (e.g., Docker secrets, environment variables, or dedicated secret managers). - High · Unsafe Docker Build Configuration —
Dockerfile (lines with conditional RUN statement). The Dockerfile uses conditional logic based on the BIN_PATH argument that skips building if a file already exists. This could lead to using stale binaries and introduces unpredictable behavior in CI/CD pipelines. Additionally, the build stage accepts an arbitrary BIN_PATH argument without validation. Fix: Remove the conditional build logic and always rebuild binaries from source. Validate the BIN_PATH argument to prevent path traversal attacks. Use proper versioning and tagging strategies. - Medium · Missing HEALTHCHECK Directive —
Dockerfile. The Dockerfile does not include a HEALTHCHECK instruction, making it difficult to determine if the application is running correctly in container orchestration environments. Fix: Add a HEALTHCHECK directive that periodically verifies the application is responsive (e.g., checking an RPC endpoint or health endpoint). - Medium · Dependency Version Pinning Issues —
package.json (dependencies section). The package.json uses caret (^) version specifications for critical dependencies like @tanstack/react-query, react, and react-router-dom. This allows automatic updates to minor/patch versions which could introduce breaking changes or security vulnerabilities. Fix: Pin exact versions (remove ^ operator) for production dependencies, especially security-sensitive libraries. Use automated dependency scanning tools (e.g., npm audit, Dependabot) and regularly update dependencies in a controlled manner. - Medium · Potential Exposure of Sensitive Configuration Files —
.docker/volumes/node_*/config.json, genesis.json, polls.json, proposals.json. The repository contains committed configuration files (config.json, genesis.json, polls.json, proposals.json) in .docker/volumes/ directories. While these may be test configs, they could contain sensitive network parameters or addresses that shouldn't be public. Fix: Review committed config files for sensitive data. Use templates or environment-based configuration for deployment-specific settings. Consider moving test configs outside the main repository or use .gitignore patterns. - Medium · Missing npm Audit Configuration —
package.json (missing audit configuration). The package.json does not explicitly configure npm audit settings or security policy. Vulnerable dependencies could go undetected in the supply chain. Fix: Add.npmrcfile with audit settings. Integrate npm audit into CI/CD pipeline. Usenpm ciinstead ofnpm installin production builds. Configure audit exceptions only for justified cases. - Low · Loose TypeScript Configuration —
package.json (build script), tsconfig.json (not provided but referenced). The dev script runstsc -bbut there's no indication of strict TypeScript compiler options enabled, which could allow type-unsafe code patterns. Fix: Enable strict mode in tsconfig.json with settings like 'strict': true, 'noImplicitAny': true, 'strictNullChecks': true to catch potential security issues at compile time. - Low · React Version Security —
package.json (react dependency). React 19.1.1 is relatively new. While not inherently insecure, cutting-edge versions may have undiscovered vulnerabilities before broad community review. Fix: Monitor React security advisories. Consider using a slightly older stable version (18.x) if stability is prioritized over latest features. Regular update testing is recommended. - Low · Missing ESLint Security Plugin —
undefined. The ESLint configuration doesn't Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.