SourceLessExplorer · SourceLess AsgardSourceLess Asgard · chain 1313
LiveHeight23,730Head age27 sLast interval1 minFinality23,719Behind−11Pending0 / 8,192Tx in head0
XPlorer following the chain as its own read-only node

height 23730 of 23730 on the network. 9 peer(s) connected, 77 in its peer directory; 1026 block(s) followed and 854 pulled in by sync since this follower started. Caught up: this follower holds every block any peer has claimed, so every panel below is the whole chain. Genesis 1cf8655125cc1bbb…, producers genesis.

What this follower is, locally

Following 7 seed(s) — their addresses are not published here, for the reason the peer table gives. Its store is held under its own Cerberus lease — no other node’s store is opened, touched or stopped.

Fork documentation

Everything an operator needs to rehearse a business fork, launch one that can carry value, and run it: every flag and command, the endpoints, the two key paths, the governance arithmetic, what is permanent, what to check before value, and every refusal you may meet.

What a business fork is

A business fork, which SourceLess calls Vanaheim, is a new and independent chain started from the SourceLess software: its own genesis, its own chain id, its own validators and its own assembly. It runs the same code as Asgard, so it has contracts, STR.domains, encrypted storage and STR.talk from its first block. It shares nothing else with Asgard: no validators, no state and no governance. Nothing in Asgard governs it.

One command, node scripts/fork.mjs, builds the genesis, starts the validator set and prints the genesis hash and the endpoints. A fork it starts with derived keys is a rehearsal; a fork started from private production keys is a chain that can carry value.

Fork, or a token on Asgard

Most projects want a token. A ZK13 token on Asgard is one deploy record, inherits the security of the SourceLess validators, and can be replaced by deploying another. A fork is a validator set you operate for the life of the chain, and its genesis cannot be undone.

Fork only when at least one of these is true:

  • your asset must be native to the chain, not a balance in a contract;
  • your data must not sit on a chain other people read;
  • your regulator requires you to operate the validators.

If none is, start from the token template instead.

What you need

  • A build of the SourceLess software. scripts/fork.mjs runs from the source tree and starts nodes from its build, so run npm ci and npm run build first.
  • Node.js 20.11 or later. The version the package declares; the measured runs used Node 22.
  • One machine to rehearse on. Every seat of a rehearsal runs as a process on the machine that runs the command, on ports the operating system chooses, all on loopback.
  • For a chain that will carry value: production keys made privately with SourceLess, one host per seat, and a public address, a domain name and TLS for the endpoints you publish.

Rehearse a fork

One command starts a rehearsal. The command builder writes it for the values you choose.

node scripts/fork.mjs up --name "Lindworm Freight" --chain-id 606060 --validators 3 \
  --allocate treasury:STR:1000000:STR.lindwormtreasury \
  --allocate ecosystem:STR:250000 \
  --heartbeat-ms 1500

Every flag:

FlagWhat it sets
--nameThe chain's name. Required, with no default. It is in the genesis hash, so it is part of the chain's identity and cannot be changed afterwards.
--chain-idA positive integer. The ids of the realms in the register are refused by name: 31337 (dev), 131313 (Midgard), 1313 (Asgard).
--validatorsHow many seats the genesis declares, and how many processes start. Required, with no default. This is the starting producer set.
--allocateRepeatable: <label>:<token>:<whole amount>[:<STR.domain>]. The first is the treasury and must carry a domain, because an unproved wallet cannot spend. Tokens: STR, CCOS, WSTR, ARSS, STR_USD, ESTR. Whole units; the ledger has 13 decimals and the command does the arithmetic.
--owner-domainThe STR.domain that holds every genesis node. Defaults to STR. and the slug of the chain name. One genesis has one owner.
--rootWhere the data directories, the genesis and the manifest live. Defaults to .sourceless/forks/<slug>-<chain id> in the source tree.
--freshDeletes the data root first. This throws away the chain in it.
--foregroundRuns the supervisor in the terminal instead of detaching it.
--lifetime-hoursThe bound after which every node stops itself. Default 168.
--heartbeat-msQueues one real STR.domain allocation every N milliseconds so an otherwise idle chain advances. Default 0, which is off.

The banner prints the chain, the genesis hash, the register's verdict (no realm matches: this is a fork), the validator set, and for every node its seat and its endpoints.

Run, stop and resume

node scripts/fork.mjs status     # what every node holds right now
node scripts/fork.mjs seed       # give the chain work, so it advances
node scripts/fork.mjs down       # stop, keeping the chain
node scripts/fork.mjs up ...     # again: resumes from the durable log
node scripts/fork.mjs --help     # answers, and starts nothing
  • An idle chain that does not advance is not a fault. A producer with an empty queue seals nothing. Use seed, or start with --heartbeat-ms.
  • seed spends from the treasury. On a rehearsal it proves the treasury, registers four accounts and sends them transfers. On a production fork it refuses, because the treasury key is held by people and the script has none: fund accounts from a wallet that holds a production key, against the fork's RPC.
  • status, seed and down find the fork from --root, from --name and --chain-id, or from the one fork that is there.

The endpoints

EndpointWhat it isWho may reach it
rpcIris, the public JSON-RPC door, and the one a wallet comes through. POST with named parameters; positional parameters are refused. genesis answers the chain id, the genesis hash and the chain binding; getStatus the height.Wallets and applications
opsAstrolabe, read-only: GET and HEAD only.Monitoring
admin (write)The supervisor's control socket, unauthenticated, and the only write path onto a running node.Loopback only. Never expose it, on a fork or anywhere else.

Every port is ephemeral: the command binds no fixed port, so it cannot collide with anything already running. The ports of your run are in the banner and in <data root>/fork.json. Every one is loopback. A published endpoint, a domain name, TLS and a seed list are separate work, and a node refuses to publish a loopback or private address as a seed, because a seed list is read by strangers.

Keys: a rehearsal and a chain that carries value

Rehearsal: --name --chain-idProduction: --genesis --seat
Where the keys come fromDerived by the script from the chain name and idMade and held privately, never derived
Who can seal your blocksAnybody who knows the chain name and idOnly the holders of the production keys
What the banner calls itDERIVED, a rehearsal chainDELIVERED
What it is forTesting the start-up path and an application against a chain of your ownA chain anybody may put value on

A production fork's keys are made with SourceLess before launch. Then node scripts/fork.mjs up --genesis <file> --seat <dir> --seat <dir> … starts the chain from its genesis, one --seat per seat the genesis declares.

  • Both keystores on every node are sealed, and nodes run in production mode, so an unsealed validator is refused.
  • On the production path the command refuses outright when SOURCELESS_KEY_PASSPHRASE is not set.
  • A rehearsal's keys are not custody, and the script says so on every run.

The governance arithmetic

Every genesis seat carries the same voting power, 50. A parameter change passes at 51% of the total, rounded up, so the bar is ceil(seats × 50 × 51 / 100). On a small fork that is very few seats:

SeatsTotal powerBarWhat it means
315077two seats decide every chain parameter
10500255six seats
1005,0002,550fifty-one seats

Compute your bar and publish it. Adding or removing a seat after genesis is a governance action, at a 30-day delay.

What the genesis fixes, and what can change

  • Fixed for ever: the chain name and the chain id, both in the genesis hash; the allocations; and everything bound to the hash. Transaction, block and contract signatures bind it, so none replays onto another chain, and the Feeless Pool address is derived from it.
  • Changeable by your assembly, each after its delay:
ParameterRangeDefaultDelay
chain.blockTargetSeconds1–60 s3 s7 days
chain.requiredConfirmations4–127127 days
governance.votingWindowMs1 h – 30 d7 d30 days
governance.ordinaryTimelockMs7 d – 90 d7 d30 days
governance.governanceChangeTimelockMs30 d – 365 d30 d30 days

Contracts on your fork

Every contract template in this build deploys on a fork. Fork contracts lists them, and each has a draft builder: edit its constants, see the bytecode and the address, download the file.

  • The same compiler gives the same bytecode, the same STARW VM charges the same gas, and the same deployer and salt give the same address.
  • The state is your fork's alone, and contract state cannot be migrated across a genesis boundary.
  • A deploy is signed by an account holding a proved STR.domain on your fork. There is no fee to a producer.
  • A deployment of a template still carrying its catalogue examples (an "Example" name, an example ticker) is refused before a passphrase is asked for.
strblk contract template <name> > <name>.ares
strblk wallet deploy <name>.ares --dry-run --address <you>
strblk wallet deploy <name>.ares --node <your fork's RPC>

Before it signs, the wallet prints the network it is about to sign for: on your fork the realm reads unregistered, and the genesis is your fork's hash. That hash is what the signature binds.

Before your fork carries value

ConditionIf it is skipped
A real ZK13 prover is boundThe reference provider refuses to run in production, so the chain does not start.
Every allocation and every node has a private production keyDerived keys come from public seeds: anyone can sign as them.
Node keys are sealed at restProduction mode refuses an unsealed validator.
The starting validator set is chosen deliberatelyA seat short for a month: changing the set takes 30 days.
The Althing bar is computed and publishedA governance claim your own genesis contradicts.
requiredConfirmations is at least 4 (the default is 12)A block called final before anything attested to executing it. The floor of 4 enforces this.
A restore from a snapshot has been rehearsed and reproduces the state rootA snapshot that restores to a different root is a fork waiting for a restart. down then up rehearses a restart from the log; the snapshot restore is yours to run.
An endpoint, a name and a seed list anybody can reachA fork nobody can dial is a fork with one operator.

What a fork does not get

  • No shared security. Your blocks are sealed by your seats and by nobody else. The SourceLess validators do not see your chain, hold no key on it, and could not help it if every one of your nodes went down.
  • No bridge. There is no path for value to move between your chain and SourceLess, or anything else. A fork is created fail-closed: it mints no $TR and refuses every collateral record.
  • Your own validator set to recruit. The genesis set is your whole producing capacity on day one, and adding a seat afterwards is a governance action at the 30-day delay.
  • Your own custody to perform. A rehearsal fork's keys can be derived by anyone who knows its name and id, so a fork that carries value has its keys made and held privately before it launches.
  • No real ZK13 prover. The reference provider refuses to run in production until a real prover is bound.
  • No migration path. Contract state cannot be moved onto a fork or off it across a genesis boundary.
  • No endpoint anybody else can reach, out of the box. Every port the fork command opens is loopback; a published endpoint, a domain name, TLS and a seed list are separate work.

Refusals you may meet

The command saysWhy, and what to do
the chain id is a realm in the registerA fork answering to a realm's id can be mistaken for it by anything that checks an id and not a hash. Pick another id.
this is the development genesis, wholeEvery key in it derives from a public seed. Build your own with --name and --chain-id.
this genesis is a realmThe genesis hashes to a realm's pin. A fork must have a genesis of its own.
the name has no letters or digitsThe name becomes the owner domain and the directory. Pick a name a person would recognise.
no --allocateA chain with no allocation has nothing anyone can spend. Add a treasury allocation with a domain.
--allocate is not label:token:whole[:STR.domain]Labels are lower case, digits and hyphens; the token is one of the six; the amount is a whole number.
no SOURCELESS_KEY_PASSPHRASEOn the production path the sealed keystores need it. Set it in the environment the command runs in.
seed on a custody forkThe treasury key is held by people. Fund accounts from a wallet that holds one.
the height does not moveNot a refusal: an idle chain seals nothing. Run seed or use --heartbeat-ms.

Where to go next

  • The fork stack: what else runs on a fork beside its seats: the three node types, Praeco discovery, hostless storage, STR.talk and the door, each with what works today.
  • Realms: the register a fork is checked against.
  • Business forks: the short version of this page.