Some networks run several independent node implementations. EmpoorioChain runs one, empoorio-node, and this post is about what it is made of and the one build step that trips up every newcomer.
The base: polkadot-sdk
The node and runtime are built on polkadot-sdk at the stable2606 release line. That choice brings the Substrate client (networking, database, Wasm executor, RPC), FRAME (the pallet framework the runtime is written in), Aura, GRANDPA, BEEFY and the transaction pool. EmpoorioChain does not fork the SDK wholesale; it pins a release and patches what it must.
A rule that follows from this: the correct version of any dependency is the one polkadot-sdk uses, not the newest on crates.io. Pulling a newer wasmtime, libp2p or parity-scale-codec than the SDK pins produces duplicate crates in the tree and, at best, a build failure — at worst, two incompatible copies of the same type at runtime.
The patched crates
The root Cargo.toml redirects Frontier (the EVM compatibility layer) and four polkadot-sdk crates to a local patches/sdk/ directory by path. Frontier is a fork: upstream Frontier tracks its own SDK version, and making it compile against stable2606 with EmpoorioChain's runtime types required changes that live as versioned patch files in patches/sdk-parches/.
Those patched sources total about 380 MB and are git-ignored. A fresh clone does not contain them, and cargo build dies with:
failed to read …/patches/sdk/frontier/…/Cargo.toml
The fix is one command before the first build:
./scripts/restaurar_sdk_vendorizado.sh
It reconstructs patches/sdk/ from the versioned patches. Every guide in the repository now says this in a warning box, because the failure message points at a missing file rather than at the missing step.
The wasmtime episode
When the runtime moved to stable2606, the build broke on wasmtime, the WebAssembly engine the Substrate executor uses. The vendored Frontier was still pulling an older SDK version, which in turn pulled an older wasmtime; two SDKs and two wasmtime versions ended up in one dependency tree. The temptation was to force versions with [patch] overrides. The actual fix was to connect the vendored Frontier fork to the same SDK the rest of the workspace used — after which the tree had zero duplicate SDK crates and a single wasmtime 36. The lesson was recorded: when the tree has two SDKs, the problem is a crate pinned to the wrong one, not a version to override.
Build hygiene
target/reaches ~50 GB on a full release build. ANo space left on deviceerror frequently disguises itself as a compiler error; check disk before debugging Rust.CARGO_INCREMENTAL=0for release builds of the node: incremental artefacts for a workspace this size cost more than they save.- Do not benchmark or commit while a code-generation process is still writing to the tree; compare source timestamps with the build's finish time before drawing conclusions from a measurement.
Why one client
Client diversity is a real security property and EmpoorioChain does not have it yet. What it has instead is one client built from a pinned, reviewed SDK release, a reproducible build from tagged commits, and an upgrade policy that changes rules on chain rather than by asking operators to swap binaries. A second implementation is a future the runtime's on-chain metadata makes possible; it is not something to claim before it exists.
Based on GETTING_STARTED.md, VALIDATOR_GUIDE.md and the engineering notes on the stable2606 migration.


