Open-source project
crustio/crust avatar
crustio/crust

Crust: a Substrate node for decentralized storage, built and run from source

Official Rust implementation of the Crust protocol

535 stars41 forksRustApache-2.0

At a glance

What is it?
The crustio/crust repository is the Rust implementation of the Crust protocol node, built on Parity Substrate with a workspace of custom pallets for staking, a work-reporting market, claims, locks and a bridge. The README is a runbook rather than a pitch, covering three live chains, a two-node local testnet and the wasm build steps a Substrate node needs.
Who is it for?
Adopt crust if you are running a Crust node or building on the Crust protocol, and you need the source rather than a packaged binary, since the repository is the reference implementation and the workspace layout shows exactly which pallets are custom and which come from upstream. Do not adopt it as a general Substrate template, because the runtime is Crust specific and the crates in the workspace are the protocol itself.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 167 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What this repository is: a protocol node, not an SDK

This is an implementation of a Crust Protocol node with Substrate, and the badges at the top of the README place it precisely: it is built on Substrate 3.0.0, it is funded by the web3 foundation and the Substrate Builders Program, and it is licensed under Apache 2.0. The homepage is crust.network.

The word node matters. This is the software a machine runs to participate in the network, not a library you import into an application, and the repository layout is the evidence. The top level holds cstrml/ for the custom runtime modules, node/ for the node binary, primitives/ for the shared types, rpc/ for the custom RPC surface, runtime/ for the runtime crate, utils/ for helper crates, docs/, scripts/ and a docker/ directory, plus Cargo.lock, Cargo.toml and a .gitmodules file.

The .gitmodules entry is worth pausing on. Crust's own README says the default branch mainnet can be built and connected to mainnet, and a submodule directory alongside a Substrate workspace is how a project of this kind pins the upstream framework version it depends on. So the node is Crust's code sitting on top of a specific Substrate release, and the two move independently.

The README also says the project is implemented with the Crust protocol and points readers at the Crust wiki for the node overview, with a Join to Play section linking there. That is a deliberate division: this repository explains how to build and run the software, and the wiki explains what the protocol does.

The project description calls it the official Rust implementation of the Crust protocol, and the primary language is recorded as Rust with the default branch being mainnet rather than master, which matches the network-flavoured branching described in the README.

Building it: Rust, a wasm environment, and a release build

The build instructions are four steps, and step two is the one that surprises people who have not built a Substrate node before.

First, Rust itself:

shell
curl https://sh.rustup.rs -sSf | sh

with a note that if rustc --version fails in the console afterwards, the Rust install page is the place to repair it.

Second, initialising the wasm build environment:

shell
./scripts/init.sh

This is a shell script in the repository rather than a manual step, and its existence tells you the wasm toolchain setup is fiddly enough to deserve automation. A Substrate node compiles its runtime to WebAssembly so the chain logic can be upgraded independently of the client, and that requires a wasm compiler and the right target installed and configured. The scripts/ directory in the repository root is where that lives.

Third, the build itself, which produces both halves:

bash
cargo build --release

The step is titled Build wasm and native code, and the two outputs matter. The wasm runtime ends up in the binary as a blob, while the native code is the client. The release profile in the Cargo.toml sets panic = 'unwind' under profile.release, which is a specific and deliberate choice, since unwinding rather than aborting keeps panics recoverable at the cost of a slightly larger binary.

The fourth step is troubleshooting rather than a command, and it lists per-distribution packages. On Debian, Ubuntu and Raspbian the list starts with sudo apt install gcc-multilib, then fetches the LLVM 10 install script from apt.llvm.org, makes it executable, runs it as root with a version argument of 10, and symlinks llvm-config into the user bin directory, followed by installs of gcc and clang. On Fedora, RedHat and CentOS the equivalent is two yum installs, gcc and clang, with the -y flag so no confirmation is needed.

The README frames that troubleshooting section by saying that if you cannot build the source code, check the detailed error message and try the corresponding commands. The pattern is worth noting: the fixes are compiler-specific, so the right answer depends on what your distribution ships, and the multiarch gcc-multilib package is the one that is easy to miss on a 64-bit machine.

Three live chains, and the flag that makes syncing bearable

The live network section is where the README is most useful, because it names the chains and the branches that correspond to them.

Mainnet is the default. The default branch mainnet can be built and connected to mainnet:

shell
./target/release/crust --chain mainnet

And then the performance note, which is one line and matters a great deal in practice. To speed up the synchronization process, add the following parameters:

shell
--execution=wasm --wasm-execution=compiled

By default Substrate nodes interpret wasm runtime calls rather than compiling them to native code, and the difference is not marginal. A node syncing from genesis executes a great deal of runtime logic, and interpreting that instead of compiling it is the difference between a sync that finishes and one that does not. Any deployment with a storage budget or a patience budget should treat these flags as part of the standard invocation rather than an optimisation.

The second chain is maxwell, and it comes with a version instruction rather than a branch name for the whole build. Please checkout the branch release/0.11.1, then build and connect to maxwell:

shell
./target/release/crust --chain maxwell

So maxwell is a separate line with its own release branch, which means an operator who wants to run it is building from a different tree than a mainnet operator. The bootnodes for that chain come from a JSON file in the maxwell branch of the repository, hosted on raw.githubusercontent.com, which is the usual way a chain publishes its peer list.

The third is rocky, the free test network. Rocky has the same function and parameters as mainnet, and developers can deploy applications on it:

shell
./target/release/crust --chain rocky

The wording is worth noting. Rocky has the same function and parameters as mainnet, which is the useful property for a test network: an application deployed against rocky exercises the same chain interfaces it will meet in production, so the test network is a genuine rehearsal rather than a simplified environment.

Three chains, one binary, and a `--chain` argument to select which genesis the node loads. That is the Substrate chain-specification model doing its job, and it is why the branches matter less than they would in a codebase with hard-coded genesis values.

The local two-node testnet, and why Alice and Bob are spelled out

The dev network section covers two things: running a single developer chain, and running a two-validator local network so you can watch consensus happen.

The single-node path starts with clearing any existing developer chain state:

bash
./target/release/crust purge-chain --dev

and then starting the chain:

bash
./target/release/crust --dev

The purge step is not optional in practice. A developer chain stores state on disk, and a schema or genesis change between runs leaves you with state that no longer matches, so purging first is the habit that prevents a confusing afternoon.

For detailed logs, the README points at the same command run with the RUST_LOG and RUST_BACKTRACE environment variables set to debug and 1 respectively, and with cargo run in place of the release binary.

The two-node path is the more interesting one, and the README walks through it in a way that teaches the model. If you want to see the multi-node consensus algorithm in action locally, you create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain and have been endowed with testnet units.

Alice starts first, on the default TCP port 30333, with her chain database at /tmp/alice:

bash
./target/release/crust \
  --base-path /tmp/alice \
  --chain local \
  --alice \
  --node-key 0000000000000000000000000000000000000000000000000000000000000001

Bob then starts in a second terminal on port 30334, with his own base path, and connects to Alice using the --bootnodes option:

bash
./target/release/crust \
  --base-path /tmp/bob \
  --chain local \
  --bob \
  --port 30334 \
  --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp

Two details are worth noticing. The --node-key value for Alice is the well-known dev account key of 0000...0001, and the README says the bootnode ID her node generates from that key is 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp, which is exactly what Bob is told to dial. So the peer ID is not a copy-paste of some other network's node; it is derived from the key you chose, and the README tells you how to check it.

And the --base-path separation is what keeps the two chains independent on one machine, with /tmp/alice and /tmp/bob rather than a shared default data directory. Everything else about the pair, the ports, the roles, the bootnode address, is ordinary multi-node setup that the Substrate tooling provides.

The workspace, and which parts of Crust are custom

The Cargo.toml is the most informative single file in the repository, because it names every crate in the workspace and therefore tells you where the protocol logic lives.

The workspace is declared with a resolver of 2, and the exclude list removes five utility crates from the workspace: utils/webpki, utils/ring, utils/serde_json_no_std, utils/serde_derive_no_std and utils/serde_derive_no_std. Excluded crates are built separately rather than as part of the workspace build, and the fact that the list contains webpki, ring and the no_std serde forks tells you the project carries patches of its own for cryptography and no-std support.

The member list starts with the utility crates and then the protocol ones:

toml
members = [
    'utils/inverse-funtion',
    'cstrml/balances',
    'cstrml/claims',
    'cstrml/staking',
    'cstrml/swork',
    'cstrml/market',
    'cstrml/locks',
    'cstrml/benefits',
    'cstrml/csm-locking',
    'cstrml/bridge',
    'cstrml/bridge-transfer',
    'cstrml/swork/benchmarking',
    'runtime',
    'rpc',
    'node',
]

The cstrml/ prefix is the giveaway that these are forks or extensions of Substrate's own pallets. balances, staking and claims sit alongside the ones that are clearly Crust specific: swork, market, locks, benefits, csm-locking, bridge and bridge-transfer.

The names describe the protocol without needing the wiki. swork is the work-reporting pallet, and it has its own benchmarking sub-crate, which is the standard Substrate way to provide benchmark numbers for weight calculation. market pairs with swork, which is consistent with a design where reported work is priced and matched. locks and csm-locking are storage-locking mechanisms, and benefits look like the incentive side of that. The bridge pallets are the cross-chain side, and the presence of a separate bridge-transfer crate suggests the transfer path is treated as distinct from the bridge registration path.

The final three members are the assembly: runtime/ is the runtime crate that wires the pallets together, rpc/ holds the custom RPC methods the node exposes, and node/ is the binary. That layering is the standard Substrate shape, and it is why the runtime can be compiled to wasm independently of the node.

The repository also carries a docker/ directory with its own instructions for building and running the node in a container, and a docs/ directory containing the contribution guidelines the README links to.

Contributing, licensing, and what this repository does not tell you

The contribution guidance is a paragraph, and it points rather than explains. Please follow the contributions guidelines as outlined in docs/CONTRIBUTION.md, and in all communications and contributions the project follows the Contributor Covenant Code of Conduct, linking the Parity Substrate version of that document.

That is the right level of detail for a README of this size. The contribution file is where the review process, branch naming and commit conventions live, and the code of conduct being hosted with the upstream framework project rather than copied into this repository is a small sign that Crust runs on Substrate's community norms rather than inventing its own.

The licence is Apache 2.0, with the full text in the LICENSE file at the root.

What the README does not cover is the protocol itself. There is no explanation of what the market pallet does, how swork reports are validated, how the bridge handles trust assumptions, or what the difference is between the three chains beyond their names. For that, the README sends you to the Crust wiki and its node overview page, and the substrate and Crust protocol links in the opening line are the other two references.

The same applies to the RPC surface. The rpc/ crate is in the workspace, so there are custom endpoints, and the README says additional CLI usage options may be shown by running cargo run -- --help, but it does not list them. If you are integrating against a Crust node programmatically, the endpoint list is something you will need to find in the rpc crate or in the wiki.

One more limitation worth naming is that the fast sync guidance is given as a bare flag with no explanation of the tradeoff. The compiled wasm execution mode is faster to sync, and it is what you want in practice, but the README does not say whether it changes anything about behaviour during execution, and that is the kind of question the documentation or the chain community would answer.

The overall shape of the project is then clear. This is an implementation, kept up to date with three live chains and a reproducible local testnet, where the code is the authoritative artefact and the wiki carries the explanation. The release tags follow the same pattern, with crust-mainnet-26 dated 2025-05-07, crust-mainnet-25 from 2024-09-11 and crust-mainnet-24 from 2024-08-15, each named as a Crust Mainnet Release.

Editorial conclusion

Adopt crust if you are running a Crust node or building on the Crust protocol, and you need the source rather than a packaged binary, since the repository is the reference implementation and the workspace layout shows exactly which pallets are custom and which come from upstream. Do not adopt it as a general Substrate template, because the runtime is Crust specific and the crates in the workspace are the protocol itself. Before you build, run the init script so the wasm toolchain is in place, and before you sync a node, add the compiled wasm execution flags, since the default interpretation is markedly slower.

Frequently asked questions

How do I build the Crust node from source?

Install Rust with curl https://sh.rustup.rs -sSf | sh, initialise the wasm build environment with ./scripts/init.sh, then run cargo build --release, which produces both the wasm runtime and the native client. On Debian-family systems the troubleshooting steps include sudo apt install gcc-multilib and the LLVM 10 installer script.

Which networks can the Crust node connect to?

Three. Mainnet is built from the default mainnet branch with ./target/release/crust --chain mainnet, maxwell is built from the release/0.11.1 branch with --chain maxwell, and rocky is the free test network with --chain rocky, which the README says has the same function and parameters as mainnet.

How do I speed up syncing a Crust node?

Add the parameters --execution=wasm --wasm-execution=compiled to the node command, which the README recommends specifically to speed up the synchronization process compared with the default interpretation of wasm runtime calls.

How do I run a two-node local testnet for Crust?

Start Alice first on port 30333 with --base-path /tmp/alice, --chain local, --alice and the dev node key, then start Bob in a second terminal with --base-path /tmp/bob, --chain local, --bob, --port 30334 and a --bootnodes argument pointing at Alice's peer ID on port 30333.

Which pallets are custom to the Crust protocol?

The workspace members under cstrml include swork, market, locks, benefits, csm-locking, bridge and bridge-transfer alongside forks of balances, staking and claims, plus the swork benchmarking sub-crate. The runtime, rpc and node crates assemble them into the running chain.

Official sources

  1. crustio/crust on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/crustio-crust.svg)](https://hysenlabs.com/projects/crustio-crust)

Was this useful?