Update, random number generator could likely be massively simplified. The "draw a vote from the hat each block", if you make the votes secret to prevent DoS on block producer (and block producer knows the decryption key, or nonce for the preimage for the vote, the voter gave it to them), you provide randomness each block. This randomness is parallelized, contrary to for when validators pre-commit hash onions, and with sufficiently many voters the problem with forks that the validator hash onion variant has - you expose the hash onions of the validators reveled on abandoned fork and can attack the alternation sequence - disappears in the sheer number of voters to pick from, millions or billions. You also do not need to pre-register validators, they can be fully anonymous and unknown until the point they publish the block, just like in proof-of-work. Updated spec:
# Fractal Social Hierarchy UTXO System with Universal Basic Income by Demurrage
A population register and a UTXO payment layer. The register is a social hierarchy: your superior attested your identity. Being registered gives you universal basic income, claimable as UTXO. All UTXO values decay at 20% per year — this decay is the UBI. The people vote for block validators. Each vote is a hash commitment. One vote is drawn randomly each block — the selected validator reveals the preimage, which seeds the random selection of the next. The secret votes prevent DoS attacks on block producers and provide the random number generator, all in one.
## Node
```
Node {
key pubkey
children []hash
leaf bool
nonce uint
last_ubi uint
last_vote uint — timestamp of last vote claim
tree_count uint — persons in subtree
tree_ubi uint — unclaimed UBI in subtree (normalized)
}
```
A node is a person, a group of persons, or an organization. One key per node.
A person contributes 1 to tree_count. A group represents multiple persons as a single node (contributes N). An org is a non-person entity (contributes 0 — no UBI).
`tree_count` is the number of persons in the subtree, aggregated upward. Population = root.tree_count. A node's own person contribution is tree_count minus the sum of its children's tree_counts.
`last_ubi` is the timestamp of the node's last UBI claim.
`leaf` — if true, the node cannot have children. Set by the parent at creation.
## UTXO
```
Output {
amount uint
time uint
owner pubkey
}
```
Real value at time T: `amount × decay^(T − time)`.
Identified by `(tx_hash, index)` where `tx_hash` is the hash of the transaction that created it. Spent outputs are removed from the set.
## Decay
20% per year. Per-second factor at scale 10^16: `decay = 9999999929290076` (~0.8^(1/31557600)). Computed via binary exponentiation with floor rounding at every step, guaranteeing bit-reproducible results across implementations.
## UBI
Each person accrues UBI continuously. Claimable amount at time T:
```
claimable(T) = contribution × TOKEN × (1 − decay^(T − last_ubi))
```
TOKEN = 10^16 base units. `contribution` is the node's own person contribution (tree_count minus sum of children's tree_counts).
A person accrues up to 1 TOKEN. A group of 5 accrues up to 5. An org: nothing.
In equilibrium: total supply converges to population × TOKEN. Total decay across all UTXOs equals total UBI minted.
## Supply
Both the UTXO trie and the people tree normalize values to a shared reference time `norm_time`, periodically advanced from Unix time 0.
UTXO trie: each output's amount is normalized at insert: `normalized = amount / decay^(time − norm_time)`. Internal trie nodes sum their children. Total supply at time T: `root.sum × decay^(T − norm_time)`.
People tree: `tree_ubi` is normalized the same way. Unclaimed UBI at time T: `tree_count × TOKEN − root.tree_ubi × decay^(T − norm_time)`.
Invariant: `utxo_supply + unclaimed_ubi ≈ tree_count × TOKEN`. Verifiable from the two roots without traversal.
## UBIClaim
```
UBIClaim {
key pubkey
outputs []Output
nonce uint
sig sig
}
```
Mints UBI. `key` must exist in the tree with contribution > 0. Sum of output amounts must equal `claimable(T)`. Nonce matches the node's nonce. Signed by `key`.
Processing: create outputs with `time` = block time. Update `last_ubi` to block time. Increment nonce.
Outputs can be owned by any pubkey — not necessarily the claimer's tree key.
## Transfer
```
Transfer {
inputs []Outpoint
outputs []Output
sigs []sig — one per input
}
Outpoint {
tx hash
index uint
}
```
Spends UTXOs and creates new ones. Each input is signed by its owner — different owners can participate in the same transaction.
Validation: each input exists and is unspent. Sum of output amounts ≤ sum of input real values at block time. Difference is the transaction fee, collected by the validator.
Processing: remove spent inputs from the UTXO set. Create new outputs with `time` = block time.
## Tree Operations
### Add
```
Add {
parent pubkey
child pubkey
hash bytes[32]
nonce uint — parent's nonce
consent sig — child signs hash + nonce + parent pubkey
sig sig — signed by parent
}
```
Parent adds child. Subtree verified by hash. `last_ubi` = block time for all nodes in the subtree. Increment parent's nonce. Recompute `tree_count` upward.
### Remove
```
Remove {
parent pubkey
child pubkey
nonce uint — parent's nonce
sig sig — signed by parent
}
```
Child and its entire subtree are deleted from the tree. Accrued UBI for each person in the subtree is automatically minted as UTXOs to their respective keys. Increment parent's nonce. Recompute `tree_count` upward.
### Rekey
```
Rekey {
old pubkey
new pubkey
nonce uint
sig sig — signed by old key
}
```
Changes a node's key. Increment nonce.
## Block Production
Each block is produced by a validator selected via the election trie. The selected candidate signs the header and reveals one layer of the hash onion committed in their vote entry: `rand = prev_rand XOR revealed`. Every layer was pre-committed before `rand` was known — uncontrollable and unpredictable.
If the selected candidate is offline, the slot is skipped. Fork choice: the chain with the fewest skipped slots relative to its length wins.
### Bootstrapping
The genesis header includes an `election_trie` with at least one committed vote. This is sufficient for the initial validator to produce blocks until the population votes for the next.
## Election
Validator selection operates in fixed-length periods. Each period, vote tokens are claimed, mixed, and committed into `next_election`. At the end of the period, `next_election` becomes `election_trie` and a fresh `next_election` opens. One committed entry is selected each block — its candidate validates that block.
### Election Trie
Each internal node carries the count of committed entries in its subtree. The root gives the total — the pool size for RNG selection. Committed entries count as 1, uncommitted as 0.
### Entry
An entry in the election trie is either uncommitted or committed.
Uncommitted: `{amount, owner}`. Mixable.
Committed: `{commit, owner?}`. Amount=1, locked. `commit` is the top of a hash onion: `H(candidate || H(candidate || ... H(candidate || seed)))`. Depth chosen by the voter — determines how many times the entry can be selected. The seed is shared with the candidate in advance. `owner` is optional — a ledger may use it to share transaction fees with voters.
### Transaction
One transaction type handles claiming, mixing, and committing.
Inputs: VoteClaims (mint new tokens) and/or existing uncommitted entries. One signature per input.
Outputs: uncommitted `{amount, owner}` and/or committed `{commit, owner?}`. Committed outputs must have amount=1.
Constraint: sum of inputs = sum of outputs.
```
VoteClaim {
key pubkey
nonce uint
sig sig
}
```
A VoteClaim is a special input that mints vote tokens. `key` must exist in the tree with contribution > 0. Amount = contribution. Updates `last_vote` to block time. Increments nonce. Can be combined with other inputs and outputs in the same transaction — allowing immediate mixing or committing.
### Activation
Each period has two phases. In the first half, `next_election` is open — tokens can be claimed, mixed, and committed. At the midpoint, `next_election` locks. At the end of the period, `next_election` becomes the new `election_trie` and a fresh `next_election` opens.
The lock-to-activation gap ensures no one can predict which position the RNG will select.
### Selection
`rand mod total_committed` selects a position. The trie's cumulative sums enable traversal to the selected entry.
The selected candidate reveals one onion layer in the header. Verification: `H(header.validator || revealed) == entry.commit`. The entry's commit is updated to the revealed value. `rand = prev_rand XOR revealed`.
## Header
```
Header {
seq uint
time uint
people_tree hash
utxo_trie hash
election_trie hash
next_election hash
prev hash
validator pubkey
rand hash — prev_rand XOR revealed onion layer
sig sig — signed by validator
}
```
`people_tree` is the Merkle root of the node tree. `utxo_trie` is the root of the UTXO trie. `election_trie` is the active election trie.
## Hash
H(Node) = SHA-256(key || children || leaf || nonce || last_ubi || last_vote || tree_count || tree_ubi).
## Primitives
SHA-256, Ed25519. Amounts are unsigned 128-bit integers at scale 10^16 (1 TOKEN = 10^16 base units). All signatures include an opcode.
## Civil registration compatibility
The tree structure maps onto existing population registration infrastructure. A country, region, municipality, or village can be an org node with its citizens as children. The hierarchy does not prescribe a specific administrative structure — any nesting of individuals, groups, and organizations works.