← Back to Blog

Inside v0.17.0: Security & Efficiency Hardening

·Shell Chain Team
releasesecurityperformancesupply-chain

Why a release with "no new features" matters most

Most blockchain releases compete on what is added. v0.17.0 is deliberately about what was tightened: structural debt repaid, latent attack surface closed, and the gap between spec'd and enforced shrunk to zero.

This is the kind of release that does not produce a hero metric. It is the kind of release that lets the next twelve months of features be built safely.

If you are evaluating Shell Chain for capital allocation or for a production deployment, v0.17 is the version that matters. Here is what changed.


1. Architecture re-split — workspace grew from 12 to 19 crates

The original M0 workspace had 12 crates. Over twelve months a few of those became too large to reason about — shell-network was carrying both gossip and consensus messaging; shell-consensus had absorbed the slashing logic even though it depended on storage and mempool concerns.

v0.17 split them out:

Old crate New crates
shell-network shell-network + shell-network-gossip + shell-network-rpc
shell-consensus shell-consensus + shell-consensus-slashing + shell-validator-set
shell-mempool shell-mempool + shell-mempool-policy
shell-storage shell-storage + shell-storage-cold + shell-storage-profile

The benefits are not cosmetic:

  • Cyclic dependencies eliminated. cargo-modules confirms a strict DAG. This unlocks parallel compilation and cleaner external auditing.
  • Per-crate test budgets. Each new crate has its own tests/ directory and its own CI gate. The 1,200-test number is still aggregate but each gate is now a sub-budget, not a global pool.
  • External integration surface. A wallet provider can depend on shell-network-rpc without pulling in the consensus engine.

2. Consensus slashing wired in

In M3 we shipped a governance contract that declared slashing penalties for double-signing and for unavailability. In M3–M16 those penalties were never actually enforced — the wPoA validator set was small and trusted, and slashing was a roadmap item.

v0.17 closes that gap. The new shell-consensus-slashing crate:

  • Watches for double-sign evidence in gossip and on chain.
  • Verifies the evidence cryptographically (a Dilithium3 sig over two conflicting block hashes from the same validator at the same height).
  • Emits a SlashingEvent that the next block producer must include — failure to include is itself a slashable downtime offence.
  • Decrements the validator's stake in the on-chain ValidatorSet at the next epoch boundary.

The penalty schedule is configurable per network. Testnet defaults to soft penalties (warning + temporary jail); mainnet defaults will be published with the validator economics paper.


3. Network amplification fix

A pre-v0.17 issue surfaced in adversarial gossip testing: a malformed peer could announce a block hash without producing the body, then keep re-announcing it on every gossipsub heartbeat. Honest peers would re-pull the announcement and re-broadcast it. The amplification factor in a fully-meshed test cluster was measured at ~7× of the original malformed message size.

v0.17 fixes this in three places:

  • Per-peer announcement budget. Each peer is rate-limited to gossip_announces_per_minute = 600 per topic; bursts above that are dropped silently.
  • Hash-availability cache. A negative-result cache on body fetch (with TTL) means a missing body is not re-asked of the same peer for 60 seconds.
  • Reputation decay. Repeated missing-body responses lower a peer's reputation; below a threshold, the peer is disconnected and its IP blacklisted for the configured cool-down.

Backported to v0.16.x as a security advisory; v0.17 ships with the fix on by default.


4. Bounded mempool channels

The Tokio mpsc channels inside the mempool were previously unbounded. That made the code simpler but had a failure mode that was hard to observe: under sudden load, the channel would silently grow into the gigabytes before the OS killed the process for OOM.

v0.17 introduces:

  • Configurable boundsmempool.channel.tx_inbound = 10_000 is the default; it is a single config knob.
  • Back-pressure as a metricmempool_channel_full_total{channel=…} is a Prometheus counter you can alert on. A spike means "load is approaching a degradation threshold," not "process is about to die."
  • Drop policy — the oldest-N or lowest-fee-N transactions are dropped first when a bound is hit, instead of new transactions being silently rejected.

In load tests, the new model degrades smoothly from 100% admission at 500 tx/s to 80% admission at 5,000 tx/s. The old model degraded from 100% to zero over the same range, with an OOM at the end.


5. Supply-chain CI is blocking

Five new gates run on every PR and on every nightly main build:

  • cargo audit — checks every dependency against the RustSec advisory database. Any unaddressed Critical or High advisory fails the build.
  • cargo deny — license, advisory and source-pinning checks. The workspace has an explicit allowlist; any new dependency from a non-allowlisted source fails.
  • SBOM generationcargo cyclonedx produces a CycloneDX SBOM that is attached to every release artifact.
  • Sigstore signing — release binaries are signed with cosign against the project's Sigstore identity. Verification instructions are published with every release.
  • Reproducible builds — release binaries are built with --locked --frozen from a pinned Rust toolchain in a hermetic container. The release workflow publishes the build log so a third party can rebuild and compare hashes.

Together, these close the supply-chain class of attacks — the one that took down xz-utils, took down the npm event-stream package, and is the single most likely vector for a sophisticated attacker against a production blockchain.


What did not change

We are explicit about scope:

  • No new EVM opcodes. Cancun spec parity remains the floor.
  • No new signature schemes. Dilithium3 + SPHINCS+ remain the supported set. (Hybrid PQ + ECDSA modes are a research direction, not a roadmap item.)
  • No tokenomics changes. v0.17 is a pre-token release; economic parameters are still draft.

Upgrading from v0.16.x

For node operators, the upgrade is non-breaking: stop the node, replace the binary, restart. State and storage formats are wire-compatible. The new mempool config bounds are optional — defaults match previous behaviour.

For developers depending on Shell crates, the workspace re-split means some import paths moved. The migration is mechanical and documented in docs/migration-v0.17.md.


What this means for the next twelve months

v0.17 is the operational floor we wanted before opening the chain to external validators. With slashing enforced, supply-chain CI gating every dependency change, and the mempool bounded under load, the public incentivised testnet (M14 on the public timeline) can proceed without carrying inherited debt.

Full release notes: v0.17.0. PR: #22.