Stars and roles
Every participant in the network is a Star: a record in StarRegistry with an owner, a signing key, a role and the epoch it registered in.
struct StarInfo { address owner; // cold wallet, receives rewards address signer; // hot key on the server Role role; // None | Node | CP | Banned uint64 registerEpoch;}Two keys
Section titled “Two keys”The owner is a cold wallet. The money goes there, and it is the only address that can change anything about the Star. Ownership cannot be transferred: the owner is set at registration and stays for good.
The signer is a hot key on the server. The program signs its working messages with it: intervals served, reports, calls to other participants.
- A node sends no transactions with its signer.
- A Control Plane does: publishing time served and relaying gas-free operations are paid from the signer’s address. That address needs ETH.
Taking over the server gets you the signer, not the money: claimNode and claimCp read the payee from the registry, not from whoever made the call.
One address can sign for only one Star. register and updateSigner refuse a signer that already belongs to another.
After a break-in
Section titled “After a break-in”StarRegistry.updateSigner(starId, newSigner)Only the owner can call it, from the cold wallet. In the same transaction the old key stops being associated with the Star, and anything signed with it afterwards belongs to nobody. A signer already bound to another Star is refused.
In Stargate this is the Rotate signer button on the Star’s card — the same call, signed by the same wallet.
A full recovery goes like this:
- Shut the compromised server down.
- Bring up a clean one and take its new signer address from the startup banner.
- Call
updateSignerfrom the owner wallet.
A node’s signer holds no ETH. A Control Plane’s holds only a little — see funding the signer — so there is nothing worth moving off the old address.
The four roles
Section titled “The four roles”| Role | Value | What it means |
|---|---|---|
None | 0 | No Star: never registered, or deregistered |
Node | 1 | Carries traffic, earns from the node pool |
CP | 2 | Issues sessions and publishes time served, earns from the CP pool |
Banned | 3 | Blocked: earns nothing and cannot publish |
The node pool and the CP pool are separate money, filled by different shares of each Orbit payment. A Control Plane takes no cut of what nodes earn.
Becoming a node
Section titled “Becoming a node”StarRegistry.register(signer)Anyone can call it. No stake, no queue, no approval. It returns a starId, and the role is Node straight away. One owner can hold any number of Stars.
To leave:
StarRegistry.deregister(starId)Owner only, and only while the role is Node. A Control Plane is demoted first.
Becoming a Control Plane
Section titled “Becoming a Control Plane”For now, during the test stage, the founder grants the CP role by hand, by calling forceSetRole, which only the registry’s owner can do. If you want to run a Control Plane, get in touch. The contracts have no other way to get the role yet.
Later the role will need nobody’s decision. A Star puts up a stake, and if it meets the requirements the contract promotes it to Control Plane by itself. The requirements — the size of the stake and the conditions for promotion — will in the end be set by the DAO, not the founder.
Why not this way from the start: whoever grants the CP role decides who clients get their sessions through, so granting it is opened up last, once reports of work and penalties for dishonest ones have been proven.
Everything else already needs nobody’s permission. The endpoint list is public, clients poll it themselves and choose by response time, and joining the federation does not need the other members’ consent.
Bans and slashing
Section titled “Bans and slashing”forceSetRole(starId, Banned, withSlashing) blocks a Star. The second argument adds a permanent mark:
slashedCp[signer] = trueThe mark is set only when the Star’s previous role was CP. Banning a node with the flag does nothing extra. Once set, the mark is never cleared, and both EpochAttestations.push and RewardDistributor.claimCp refuse a marked signer.
The mark sits on the address, not on the Star. Rotating to a new signer gives the Star a clean key, and the old address stays marked for good.
A Control Plane’s endpoint
Section titled “A Control Plane’s endpoint”CPEndpointRegistry.setEndpoint(starId, host, port) is called by the Star’s owner, and only while the role is CP. Port 0 means “the protocol’s default” and is stored as such.
If the Star loses the role, the row stays, but that does no harm: every read checks the role again, so getActiveEndpoints() stops returning a demoted Star at once. Anyone can free the storage with cleanupStale(starIds).
CPEndpointRegistry.setRealityKey(starId, key) publishes the public key of the Control Plane’s front, 32 bytes. Same rule: the owner, while the role is CP. getRealityKey(starId) returns the key, or zero for a Star that is not a Control Plane, and clearEndpoint removes the key together with the endpoint.
