Governance
A proposal to move one consensus parameter, and a ballot whose power is your weight multiplied by what you spend. Money alone buys nothing here, and neither does a history you manufactured.
Using it
./baklava propose -param proposer_seats -value 2
./baklava vote -proposal fd112a3d... -spend 5000000
./baklava vote -proposal fd112a3d... -spend 5000000 -against
./baklava proposalsOr /propose, /vote and /proposals from the console. Only a registered member may open one or vote on one.
Two exponents, and only one of them was a choice.
Voting power is maturity^a × reliability^b × BKLV spent. The exponent on the spend is exactly 1, and that is not tunable: it is what makes the ballot sybil-neutral. Splitting a holding across a hundred identities gives a hundred times a hundredth, which is what you started with.
And a and b are both 1 too, which collapses the whole thing to weight × spend — because weight is maturity times reliability. Any other pair would have been a number invented against an imagined community. This one is a definition the chain already had.
Why a ballot has to cost something
Weight alone cannot decide a vote, and the reason is invisible until somebody counts. Maturity is the logarithm of an age, which is concave in one identity's history — so splitting into many identities multiplies it:
| Who | Weight |
|---|---|
| One participant, one year old | 24.9 |
| One attacker, a hundred identities, thirty days old | 2130 |
Eighty-five times the voice, for a hundred registration stakes and a hundred cheap servers run for a month. So the ballot needs a resource that is conserved when it is split, and there is only one: money. A hundred identities do not multiply a holding.
The spend goes to the treasury and does not come back. Voting again costs again — which is not a rule anybody added, but what linearity already says: a hundred votes of one Krumb are exactly one vote of a hundred. The tally is never a sum over stored votes: it is a running total on the proposal's own leaf, so nothing walks the ballots and there is no double-vote check.
Which parameters, and why not the others
| Parameter | Proposable | Why |
|---|---|---|
min_stake | Until version 7 | Reversible as a number and not as an effect — see below. A genesis parameter from rule version 7 |
leader_percent, committee_percent | Yes | Shares of a pool that is emptied every block |
apprentice_percent, proposer_seats | Yes | Change the next draw and nothing already written |
epoch_length | No | Every future freeze boundary would move at once, and an epoch record's identity is a range of heights |
committee_target | No | The quorum is ⌊2·C/3⌋+1 of it. A vote that moves the quorum is a vote about whether past certificates were enough |
| The treasury | No | Redirecting the residual claimant is a transfer of every fee the chain will ever collect, dressed as a parameter |
| The upgrade schedule | No | Only a crossed readiness threshold appends to it. A schedule a ballot could write is a ballot deciding what code exists |
One rule draws the line: a parameter is proposable when a wrong value can be voted back. Everything in the top half fails safe — the chain keeps producing blocks under a bad number, and the same members can propose a better one.
One row of that table was wrong, and rule version 7 removes it.
min_stake passes the test as a number and fails it as an effect. Lower it and members register at the new price; raise it again and their entries stay — stake paid, joined_at started, seniority accumulating. The number was reversible and the set it produced was not.
The damage was bounded until now only because power is weight times spend and a newcomer's weight is the log of a few seconds. That is a property of how power is measured, not a structure, and it disappears under any rule that counts members — which is exactly what the second column below is. So this is that rule's precondition rather than a tidy-up beside it, and the two share a version.
What it costs: the entry price is a genesis parameter now, and a network that wants it raised has to say so in code and get 90% of a frozen set to run that code.
There is no quorum, and there cannot be one
The readiness threshold has a denominator: the frozen set is bounded and known before the count begins. Governance has none. Power is weight times a spend and a spend is unbounded, so there is no “total possible power” for a percentage to be a percentage of. A participation quorum here would be a fraction of a number that does not exist.
So the whole rule for a parameter change is: more power for than against carries it, and no votes is not a pass. What stops something passing on one Krumb is that it stands in public for four epochs and anybody may spend one Krumb against it — the same argument as “not running the binary is your vote”.
A spend passes on two columns, and a parameter change on one
The line is reversibility, and it is the line this whole design already draws. A parameter that passed while nobody was watching can be voted back; a payment that passed while nobody was watching cannot. So the two failures swap places, and with them which direction is safe to fail in. From rule version 7:
| Kind | What it needs |
|---|---|
| A parameter change | More power for than against. No quorum — one would make repairing a bad value as hard as making one, and hand any third of the set a free, silent, permanent veto |
| A treasury spend | That, and at least ⌊2C/3⌋+1 distinct members of the frozen set standing for it, where C is that set's members still registered at the close |
Neither column works alone. A head count is the cheapest thing on this chain to manufacture, because a head costs min_stake. A weight sum is barely better: maturity is the log of an age, so a hundred day-old members outweigh a decade of turning up. What resists identity splitting is the spend, because money is the one resource conserved when a holding is divided — and the spend is in the first column. The first prices the decision; the second says the set was actually there for it.
⌊2C/3⌋+1 is a transplant, not a derivation, and it is written down as one.
The committee's ⌊2C/3⌋+1 is derived: it is what BFT safety needs when up to a third of a room may be byzantine, and it is about disagreement rather than consent. Nothing derives a consent threshold — “enough of the set agreed” is a judgement about how much apathy should block a payment.
Given that, the choice is between inventing a number and reusing one, and this reuses the one the chain already carries. It is the same move as setting the voting exponents to 1: a definition the protocol already had, rather than a number argued into existence against an imagined community.
Counting distinct members needs a record of who voted, which governance deliberately did not have. From rule version 7 a ballot writes one — the eleventh kind of leaf in the third state table, keyed by the proposal and the voter and deleted with the proposal, so it is bounded by what is open.
It is a head and not a power, which is what keeps voting twice harmless: a second vote from one member adds power to the tally and does not add a second head. And it holds the side last cast — vote for, then against, and your head is gone, though both spends stay in the tally because both were real and both left for the treasury.
What capture actually costs here.
Power is weight times spend, so an actor with a fortune and no registry entry has a weight of zero and a product of zero. And weight cannot be bought — it is the log of an age multiplied by a record of turning up. Moving a parameter means having been here, and having done the work, and being willing to spend.
The honest limit is the other side of that: this design resists manufactured identities and does not resist concentrated wealth. The two are opposite requirements and nothing satisfies both without knowing who people are, which this chain will not do.
Spending the treasury
From rule version 6 a proposal can also move money: an amount, a recipient, and the same four epochs in public that a parameter change stands for. Voting needs no change at all — a ballot names a proposal id and does not care what the proposal says, which is what keeping the tally on the leaf bought.
./baklava spend -to bkx1... -amount 250000000
./baklava vote -proposal 133feafc... -spend 5000000Or /spend from the console.
| Only what it earned | A spend may not take the treasury below its treasury_endowment, a genesis parameter that no proposal can move. Everything above it arrived as a fee, a proposal price, a vote's spend or a released tranche. |
|---|---|
| And two thirds of the set | From rule version 7 a spend also needs ⌊2C/3⌋+1 distinct members of the frozen set to have voted for it, counted at the close. A parameter change needs nothing of the kind — see above for why the line is reversibility. |
| Checked at the close, not at the open | Against the balance as it stands when the epoch closes. Two spends that each fit alone and not together are counted in id order and the second is discarded, not clamped — a ballot that passed for one number must never quietly enact a different one. |
| A bound on a vote is not a bound on a key | The rule stops governance and nothing else. If a key exists for the treasury address, one signature empties it and no vote takes part. That is why a mainnet treasury is derived and keyless — SHA-256("baklava/treasury/v1")[:20] — with the endowment at 0, because nothing a keyless treasury holds is principal. |
What a proposal cannot do
| It cannot change a rule | A vote cannot make code exist. A ballot passing “activate version 5” has not put version 5 in anybody's binary. That half is answered by the readiness signal, which counts a fact rather than a judgement — see Upgrades and readiness. |
|---|---|
| It cannot spend the endowment | A proposal can spend the treasury from rule version 6 — see below — but only what the treasury has earned. The endowment is a genesis number no vote reaches, and a mainnet treasury has no key either, so the spend rule is the only door. |
| It cannot change how voting works | The exponents are constants, not parameters. A majority that could set b to zero would delete reliability from the ballot with its first vote and keep the majority for ever. |
| The treasury cannot vote | It is the residual claimant of every fee and the holder of the genesis distribution. A treasury with a ballot is the chain's founder holding a permanent majority. |
Rule version 4, beside the swap — and two rules since.
A rule version is a batch rather than a rule, and no chain had activated version 4 when this was written — so governance went in beside the swap rather than becoming a version of its own. The tally lives on the proposal's own leaf, which is the seventh kind in the third state table, so there is no new tree and no change to what state_root folds.
Version 6 gave that leaf a kind and a recipient, so a proposal could spend the treasury. Version 7 took min_stake off the list and gave a spend its second column, which needed an eleventh leaf kind — a ballot. Neither added a tree either.
What is standing right now
A proposal stands four epochs in public, and until this panel existed there was no public place it stood in. Read from the node as you look at it — an open proposal is not a constant this site can compile in, and the tally moves with every ballot.
Asking the node…
./baklava proposalsFour epochs is a distance in blocks and not a wait. A proposal opened at height h is counted at the first block of epoch(h) + 4, which is between 1,501 and 2,000 blocks later on a 500-block epoch — shorter the later in an epoch it was opened. There are no empty blocks, so those are blocks somebody has to send: hours on a chain being used, and never on an idle one.
What has already been counted
A counted proposal leaves no leaf at all. It is deleted at the close — leaving it would make it a row every node carries for ever — and a parameter change and a treasury payment are both enacted by the close, in no transaction. So the chain can be asked about an open proposal and cannot be asked about a finished one.
What is below is therefore two things with different standing. What each proposal asked for comes from the signed transaction that opened it. The tally is a sample, taken from a node while the proposal was still open and kept only when that node's own header named the block being read — the leaf it came from is gone, so nothing can check it now. And no row says a parameter moved: a proposal can pass and still be discarded at the close for no longer fitting.
Asking the index…
The reasoning in full, including why the tally is kept rather than computed and why the bounds are checked twice, is under Governance in the protocol document.