This is a tool to fork a creditcoin network and create a new, distinct chain with mostly the same on-chain state as the original. This is especially useful for testing runtime upgrades and migrations, as you can simulate updating mainnet while safely separating from the actual mainnet.
-
Install the rust toolchain
-
Clone the repo
git clone https://github.com/gluwa/creditcoin-fork cd creditcoin-fork -
Build it! The resulting binary will be located at
target/release/creditcoin-forkby defaultcargo build --release
First, make sure you're able to build the repo. You can then take a look at the options
by running the creditcoin-fork binary with the --help flag:
./target/release/creditcoin-fork --help- RPC access to a live creditcoin node
- Working
creditcoin-forkbinary
Run the creditcoin-fork binary. If you're not running a local creditcoin-node
accessible at ws://localhost:9944, pass the RPC URL with the --rpc flag.
For public RPC endpoints you can omit the port—e.g.
wss://rpc.usc-devnet.creditcoin.network—the tool uses 443 for wss:// and 80 for ws:// when no port is given.
Minimal example, assuming a live testnet node running on localhost and a creditcoin-node
binary is in your PATH:
./target/release/creditcoin-fork --bin creditcoin-node --orig test --base dev -o fork.jsonThis should run successfully and the fork's chain spec will be located at fork.json.
The fetched chain state is streamed to a storage cache file on disk (--storage <path>,
defaulting to <out>.storage.json) rather than held in memory, so forking large chains
(e.g. mainnet) works on machines with modest RAM. If the cache file already exists it is
reused instead of refetching — delete it (or pass a different --storage path) to fetch
fresh state.
State fetching is tuned for public load-balanced endpoints: for wss:// URLs the bulk
fetch goes over HTTPS by default (stateless requests load-balance across backends,
unlike a pinned websocket session — override with --http-rpc <url|none>), storage keys
are listed with dynamically splitting parallel range scans (--key-scan-concurrency),
and values are fetched in batches via state_queryStorageAt
(--value-batch-size, with automatic per-key fallback). Note that on large chains the
practical ceiling is usually the node's own trie iteration speed over the biggest
storage maps, not the client or network.
You can then run a node on the fork by passing the chain spec path as the --chain, for example:
creditcoin-node --chain ./fork.json --validator --mining-key 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQYThe fork always injects the dev chain’s validator genesis (Babe, Grandpa, Session, Staking) so that Alice is the sole authority. You can use any --base (e.g. dev or devnet); the fork will overwrite consensus state with the dev chain’s, so running with --alice will produce blocks.
Create the fork (example with devnet as source):
./target/release/creditcoin-fork --bin creditcoin3-node --orig devnet --base dev --name Development -o fork.json --rpc wss://rpc.usc-devnet.creditcoin.networkThen start the node:
creditcoin3-node --chain ./fork.json --validator --alice --pruning archive --base-path ./forkBy default the fork uses the runtime WASM blob fetched from the live chain. If you want to use a custom runtime, for example one with shorter epoch/era durations for faster testing—build your runtime and pass it with --runtime:
# Build the runtime (from the creditcoin3-next repo)
cargo build --release -p creditcoin3-runtime
# Create the fork with the custom runtime
./target/release/creditcoin-fork \
--bin creditcoin3-node \
--orig testnet --base testnet --name Testnet \
-o fork.json \
--rpc wss://rpc.usc-testnet2.creditcoin.network \
--usc \
--runtime /path/to/creditcoin3-next/target/release/wbuild/creditcoin3-runtime/creditcoin3_runtime.compact.compressed.wasmTo shorten epoch/era durations, edit runtime/src/lib.rs in the creditcoin3-next repo before building:
// Change epoch from 12 hours to 15 minutes:
pub const EPOCH_DURATION_IN_BLOCKS: u32 = prod_or_fast!(15 * MINUTES, BLOCKS_FOR_FASTER_EPOCH);
// ^^^^^^^^^^^^
// was: 12 * HOURS (2,880 blocks / 12 hrs)
// now: 15 * MINUTES (60 blocks / 15 min)SessionsPerEra is 2 by default, so era duration = 2 × epoch. With the change above, eras go from 24 hours to 30 minutes.