From 3ee37f4dfa18ba7382490a1eefb99a84b925f458 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Thu, 17 Sep 2020 09:54:40 +0200 Subject: [PATCH] ADR 0004: Runtime Governance --- docs/adr/0004-runtime-governance.md | 250 ++++++++++++++++++++++++++++ docs/adr/index.md | 1 + 2 files changed, 251 insertions(+) create mode 100644 docs/adr/0004-runtime-governance.md diff --git a/docs/adr/0004-runtime-governance.md b/docs/adr/0004-runtime-governance.md new file mode 100644 index 00000000000..72a1c8a50e2 --- /dev/null +++ b/docs/adr/0004-runtime-governance.md @@ -0,0 +1,250 @@ +# ADR 0004: Runtime Governance + +## Changelog + +- 2020-09-30: Add entity whitelist admission policy max nodes limit +- 2020-09-17: Initial draft + +## Status + +Proposed + +## Context + +Currently all runtimes can only be governed by a single entity -- the runtime +owner. In this regard governance means being able to update certain fields in +the runtime descriptor stored by the consensus layer registry service. On one +hand the runtime descriptor contains security-critical parameters and on the +other there needs to be a mechanism through which the runtimes can be upgraded +(especially so for TEE-based runtimes where a specific runtime binary is +enforced via remote attestation mechanisms). + +This proposal extends runtime governance options and enables a path towards +runtimes that can define their own governance mechanisms. This proposal assumes +that [ADR 0003] has been adopted and runtimes can have their own accounts in the +staking module. + +## Decision + +This proposal takes a simplistic but powerful approach which allows each runtime +to choose its governance model upon its first registration. It does so through +a newly introduced field in the runtime descriptor which indicates how the +runtime descriptor can be updated in the future. + +### Runtime Descriptor + +The runtime descriptor version is bumped to `2`. Version `1` descriptors are +accepted at genesis and are converted to the new format by assuming the entity +governance model as that is the only option in v1. All new runtime registrations +must use the v2 descriptor. + +#### Governance Model + +This proposal updates the runtime descriptor by adding fields as follows: + +```golang +type Runtime struct { + GovernanceModel RuntimeGovernanceModel `json:"governance_model"` + + // ... existing fields omitted ... +} + +// RuntimeGovernanceModel specifies the runtime governance model. +type RuntimeGovernanceModel uint8 + +const ( + GovernanceEntity RuntimeGovernanceModel = 1 + GovernanceRuntime RuntimeGovernanceModel = 2 + GovernanceConsensus RuntimeGovernanceModel = 3 +) + +// ... some text serialization methods omitted ... +``` + +The `governance_model` field can specifiy one of the following governance +models: + +- **Entity governance (`GovernanceEntity`).** This causes the runtime to behave + exactly as before, the runtime owner (indicated by `entity_id` in the runtime + descriptor) is the only one who can update the runtime descriptor via + `registry.RegisterRuntime` method calls. + + The runtime owner is also the one that needs to provide the required stake + in escrow in order to avoid the runtime from being suspended. As before note + that anyone can delegate the required stake to the runtime owner in order to + enable runtime operation (but the owner can always prevent the runtime from + operating by performing actions which would cause the stake claims to no + longer be satisfied). + +- **Runtime-defined governance (`GovernanceRuntime`).** In this case the runtime + itself is the only one who can update the runtime descriptor by emitting a + runtime message. The runtime owner (indicated by `entity_id`) is not able to + perform any updates after the initial registration and such attempts must + return `ErrForbidden`. + + The runtime itself is the one that needs to provide the required stake in + escrow in order to avoid the runtime from being suspended. This assumes that + runtimes can have accounts in the staking module as specified by [ADR 0003]. + Note that anyone can delegate the required stake to a runtime in order to + enable its operation. + +- **Consensus layer governance (`GovernanceConsensus`).** In this case only the + consensus layer itself can update the runtime descriptor either through a + network upgrade or via a consensus layer governance mechanism not specified by + this proposal. + + Runtimes using this governance model are never suspended and do not need to + provide stake in escrow. + + Runtimes using this governance model cannot be registered/updated via regular + registry method calls or runtime messages (doing so must return + `ErrForbidden`). Instead such a runtime can only be registered at genesis, + through a network upgrade or via a consensus layer governance mechanism not + specified by this proposal. + +#### Entity Whitelist Admission Policy + +The entity whitelist admission policy configuration structure is changed to +allow specifying the maximum number of nodes that each entity can register under +the given runtime. + +```golang +type EntityWhitelistConfig struct { + // MaxNodes is the maximum number of nodes that an entity can register under + // the given runtime. A zero value means unlimited. + MaxNodes uint16 `json:"max_nodes,omitempty"` +} + +type EntityWhitelistRuntimeAdmissionPolicy struct { + Entities map[signature.PublicKey]EntityWhitelistConfig `json:"entities"` +} +``` + +The new `max_nodes` field specifies the maximum number of nodes an entity can +register for the given runtime. + +When transforming runtime descriptors from version 1, an entry in the `entities` +field maps to an `EntityWhitelistConfig` structure with `max_nodes` set to zero, +denoting that an unlimited number of nodes is allowed (as before). + +### State + +This proposal introduces/updates the following consensus state in the registry +module: + +#### Stored Runtime Descriptors + +Since the runtime descriptors can now be updated by actors other than the +initial registering entity, it does not make sense to store signed runtime +descriptors. The value of storage key prefixed with `0x13` which previously +contained signed runtime descriptors is modified to store plain runtime +descriptors. + +### Genesis Document + +This proposal updates the registry part of the genesis document as follows: + +- The type of the `runtimes` field is changed to a list of runtime descriptors + (was a list of _signed_ runtime descriptors before). + +- The type of the `suspended_runtimes` field is changed to a list of runtime + descriptors (was a list of _signed_ runtime descriptors before). + +Runtime descriptors must be transformed to support the new fields. + +### Transaction Methods + +This proposal updates the following transaction methods in the registry module: + +#### Register Runtime + +Runtime registration enables a new runtime to be created or an existing runtime +to be updated (in case the governance model allows it). + +**Method name:** + +``` +registry.RegisterRuntime +``` + +The body of a register runtime transaction must be a `Runtime` descriptor. +The signer of the transaction must be the owning entity key. + +Registering a runtime may require sufficient stake in either the owning entity's +(when entity governance is used) or the runtime's (when runtime governance is +used) escrow account. + +Changing the governance model from `GovernanceEntity` to `GovernanceRuntime` is +allowed. Any other governance model changes are not allowed and must fail with +`ErrForbidden`. Support for other changes is deferred to a consensus layer +governance mechanism not specified by this proposal. + +### Messages + +This proposal introduces the following runtime messages: + +#### Update Runtime Descriptor + +The update runtime descriptor message enables a runtime to update its own +descriptor when the current governance model allows it. + +**Field name:** + +``` +update_runtime +``` + +**Body:** + +```golang +type UpdateRuntimeMessage struct { + registry.Runtime +} +``` + +The body of the update runtime descriptor message is a new runtime descriptor +that must be for the runtime emitting this message. Otherwise the message is +considered malformed. + +The actions performed when processing the message are the same as those +performed when processing the `registry.RegisterRuntime` method call, just made +on the runtime's (instead of an entity's) behalf. + +### Consensus Parameters + +#### Registry + +This proposal introduces the following new consensus parameters in the registry +module: + +- `disable_runtime_governance_models` (set of `RuntimeGovernanceModel`) + specifies the set of runtime governance models that are not allowed to be used + when creating/updating registrations (either via method calls or via runtime + messages). In case a runtime is using the given governance model, an update to + such a runtime must fail with `ErrForbidden`. + +### Rust Runtime Support Library + +The Rust runtime support library (`oasis-core-runtime`) must be updated to +support the updated and newly needed message structures (the runtime descriptor +and the update runtime message). + +## Consequences + +### Positive + +- Runtimes can define their governance model, enabling them to become more + decentralized while still allowing upgrades. + +- Runtimes using the entity whitelist admission policy can limit the number of + nodes that each entity can register. + +### Negative + +### Neutral + +## References + +- [ADR 0003] - Consensus/Runtime Token Transfer + +[ADR 0003]: 0003-consensus-runtime-token-transfer.md \ No newline at end of file diff --git a/docs/adr/index.md b/docs/adr/index.md index 1d76297aa0b..788bed8933c 100644 --- a/docs/adr/index.md +++ b/docs/adr/index.md @@ -75,4 +75,5 @@ The following records currently exist: * [ADR 0001](0001-tm-multi-root-apphash.md) - Multiple Roots Under the Tendermint Application Hash * [ADR 0002](0002-go-modules-compatible-git-tags.md) - Go Modules Compatible Git Tags * [ADR 0003](0003-consensus-runtime-token-transfer.md) - Consensus/Runtime Token Transfer +* [ADR 0004](0004-runtime-governance.md) - Runtime Governance