Skip to content

Commit

Permalink
Merge pull request #5623 from oasisprotocol/kostko/fix/rt-admission-p…
Browse files Browse the repository at this point in the history
…olicy

runtime: Add missing support for per-role admission policy decoding
  • Loading branch information
kostko authored Apr 3, 2024
2 parents 6c420cf + ff8225e commit 30968d6
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 28 deletions.
1 change: 1 addition & 0 deletions .changelog/5623.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
runtime: Add missing support for per-role admission policy decoding
31 changes: 31 additions & 0 deletions go/consensus/cometbft/apps/registry/state/interop/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func InitializeTestRegistryState(ctx context.Context, mkvs mkvs.Tree) error {
if err := runtimeID2.UnmarshalHex("8000000000000000000000000000000000000000000000000000000000000011"); err != nil {
return err
}
var runtimeID3 common.Namespace
if err := runtimeID3.UnmarshalHex("8000000000000000000000000000000000000000000000000000000000000012"); err != nil {
return err
}
// Populate nodes.
for _, fix := range []struct {
nodeSigner signature.Signer
Expand Down Expand Up @@ -152,6 +156,33 @@ func InitializeTestRegistryState(ctx context.Context, mkvs mkvs.Tree) error {
},
true,
},
{
&registry.Runtime{
Versioned: cbor.NewVersioned(registry.LatestRuntimeDescriptorVersion),
ID: runtimeID3,
EntityID: entitySigner.Public(),
Kind: registry.KindCompute,
TEEHardware: node.TEEHardwareIntelSGX,
AdmissionPolicy: registry.RuntimeAdmissionPolicy{
PerRole: map[node.RolesMask]registry.PerRoleAdmissionPolicy{
node.RoleObserver: {
EntityWhitelist: &registry.EntityWhitelistRoleAdmissionPolicy{
Entities: map[signature.PublicKey]registry.EntityWhitelistRoleConfig{},
},
},
},
},
Deployments: []*registry.VersionInfo{
{
Version: version.FromU64(123),
ValidFrom: 42,
TEE: []byte{1, 2, 3, 4, 5},
BundleChecksum: bytes.Repeat([]byte{0x05}, 32),
},
},
},
false,
},
} {
if err := state.SetRuntime(ctx, fix.rt, fix.suspended); err != nil {
return fmt.Errorf("setting runtime: %w", err)
Expand Down
70 changes: 54 additions & 16 deletions runtime/src/consensus/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,22 +458,45 @@ pub struct EntityWhitelistConfig {
pub max_nodes: BTreeMap<RolesMask, u16>,
}

/// A per-entity whitelist configuration for a given role.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub struct EntityWhitelistRoleConfig {
#[cbor(optional)]
pub max_nodes: u16,
}

/// A per-role entity whitelist policy.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub struct EntityWhitelistRoleAdmissionPolicy {
pub entities: BTreeMap<signature::PublicKey, EntityWhitelistRoleConfig>,
}

/// A per-role admission policy.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub struct PerRoleAdmissionPolicy {
#[cbor(optional)]
pub entity_whitelist: Option<EntityWhitelistRoleAdmissionPolicy>,
}

/// Admission policy that allows any node to register.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub struct AnyNodeRuntimeAdmissionPolicy {}

/// Specification of which nodes are allowed to register for a runtime.
#[derive(Clone, Debug, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub enum RuntimeAdmissionPolicy {
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
pub struct RuntimeAdmissionPolicy {
/// Allow any node to register.
#[cbor(rename = "any_node")]
AnyNode {},
#[cbor(optional)]
pub any_node: Option<AnyNodeRuntimeAdmissionPolicy>,

/// Allow only the whitelisted entities' nodes to register.
#[cbor(rename = "entity_whitelist")]
EntityWhitelist(EntityWhitelistRuntimeAdmissionPolicy),
}
#[cbor(optional)]
pub entity_whitelist: Option<EntityWhitelistRuntimeAdmissionPolicy>,

impl Default for RuntimeAdmissionPolicy {
fn default() -> Self {
RuntimeAdmissionPolicy::AnyNode {}
}
/// A per-role admission policy that must be satisfied in addition to the global admission
/// policy for a specific role.
#[cbor(optional)]
pub per_role: BTreeMap<RolesMask, PerRoleAdmissionPolicy>,
}

/// Runtime governance model.
Expand Down Expand Up @@ -753,11 +776,21 @@ mod tests {
// NOTE: These tests MUST be synced with go/registry/api/runtime.go.
let tcs = vec![
// FIXME: Change to "qmF2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0b3JhZ2Wjc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQBoZXhlY3V0b3Klamdyb3VwX3NpemUAbG1heF9tZXNzYWdlcwBtcm91bmRfdGltZW91dABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBpZW50aXR5X2lkWCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGx0ZWVfaGFyZHdhcmUAcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloHBnb3Zlcm5hbmNlX21vZGVsAA==" once cbor is fixed.
("q2F2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0b3JhZ2Wjc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQBoZXhlY3V0b3Klamdyb3VwX3NpemUAbG1heF9tZXNzYWdlcwBtcm91bmRfdGltZW91dABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBpZW50aXR5X2lkWCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGx0ZWVfaGFyZHdhcmUAbXR4bl9zY2hlZHVsZXKgcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloHBnb3Zlcm5hbmNlX21vZGVsAA==", Runtime::default()),
("q2F2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0b3JhZ2Wjc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQBoZXhlY3V0b3Klamdyb3VwX3NpemUAbG1heF9tZXNzYWdlcwBtcm91bmRfdGltZW91dABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBpZW50aXR5X2lkWCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGx0ZWVfaGFyZHdhcmUAbXR4bl9zY2hlZHVsZXKgcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloHBnb3Zlcm5hbmNlX21vZGVsAA==", Runtime {
admission_policy: RuntimeAdmissionPolicy {
any_node: Some(AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
..Default::default()
}),
// FIXME: Change to "qmF2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0b3JhZ2Wjc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQBoZXhlY3V0b3Klamdyb3VwX3NpemUAbG1heF9tZXNzYWdlcwBtcm91bmRfdGltZW91dABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBpZW50aXR5X2lkWCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGx0ZWVfaGFyZHdhcmUAcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloHBnb3Zlcm5hbmNlX21vZGVsAA==" once cbor is fixed.
(
"q2F2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0b3JhZ2Wjc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQBoZXhlY3V0b3Klamdyb3VwX3NpemUAbG1heF9tZXNzYWdlcwBtcm91bmRfdGltZW91dABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBpZW50aXR5X2lkWCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGx0ZWVfaGFyZHdhcmUAbXR4bl9zY2hlZHVsZXKgcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloHBnb3Zlcm5hbmNlX21vZGVsAA==",
Runtime {
admission_policy: RuntimeAdmissionPolicy {
any_node: Some(AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
staking: RuntimeStakingParameters {
thresholds: BTreeMap::new(),
slashing: BTreeMap::new(),
Expand All @@ -772,6 +805,10 @@ mod tests {
(
"rGF2AGJpZFggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZABnZ2VuZXNpc6Jlcm91bmQAanN0YXRlX3Jvb3RYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ3N0YWtpbmehcnJld2FyZF9iYWRfcmVzdWx0cwpnc3RvcmFnZaNzY2hlY2twb2ludF9pbnRlcnZhbABzY2hlY2twb2ludF9udW1fa2VwdAB1Y2hlY2twb2ludF9jaHVua19zaXplAGhleGVjdXRvcqVqZ3JvdXBfc2l6ZQBsbWF4X21lc3NhZ2VzAG1yb3VuZF90aW1lb3V0AHFncm91cF9iYWNrdXBfc2l6ZQByYWxsb3dlZF9zdHJhZ2dsZXJzAGllbnRpdHlfaWRYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbHRlZV9oYXJkd2FyZQBtdHhuX3NjaGVkdWxlcqBwYWRtaXNzaW9uX3BvbGljeaFoYW55X25vZGWgcGdvdmVybmFuY2VfbW9kZWwA",
Runtime {
admission_policy: RuntimeAdmissionPolicy {
any_node: Some(AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
staking: RuntimeStakingParameters {
thresholds: BTreeMap::new(),
slashing: BTreeMap::new(),
Expand Down Expand Up @@ -834,8 +871,8 @@ mod tests {
checkpoint_num_kept: 6,
checkpoint_chunk_size: 101,
},
admission_policy: RuntimeAdmissionPolicy::EntityWhitelist(
EntityWhitelistRuntimeAdmissionPolicy {
admission_policy: RuntimeAdmissionPolicy {
entity_whitelist: Some(EntityWhitelistRuntimeAdmissionPolicy {
entities: btreemap! {
signature::PublicKey::from("1234567890000000000000000000000000000000000000000000000000000000") => EntityWhitelistConfig {
max_nodes: btreemap! {
Expand All @@ -844,8 +881,9 @@ mod tests {
}
}
},
},
),
}),
..Default::default()
},
constraints: btreemap! {
scheduler::CommitteeKind::ComputeExecutor => btreemap! {
scheduler::Role::Worker => SchedulingConstraints{
Expand Down
17 changes: 13 additions & 4 deletions runtime/src/consensus/roothash/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,12 @@ mod tests {
checkpoint_num_kept: 0,
checkpoint_chunk_size: 0,
},
admission_policy: registry::RuntimeAdmissionPolicy::EntityWhitelist(
registry::EntityWhitelistRuntimeAdmissionPolicy { entities: wl },
),
admission_policy: registry::RuntimeAdmissionPolicy {
entity_whitelist: Some(registry::EntityWhitelistRuntimeAdmissionPolicy {
entities: wl,
}),
..Default::default()
},
constraints: {
let mut cs = BTreeMap::new();
cs.insert(scheduler::CommitteeKind::ComputeExecutor, {
Expand Down Expand Up @@ -299,7 +302,13 @@ mod tests {
(
vec![Message::Registry(Versioned::new(
0,
RegistryMessage::UpdateRuntime(registry::Runtime::default()),
RegistryMessage::UpdateRuntime(registry::Runtime {
admission_policy: registry::RuntimeAdmissionPolicy {
any_node: Some(registry::AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
..Default::default()
}),
))],
// FIXME: Change to e6e170fb771583147255e0c96dc88615d4fd2fd28488ae489df01da201affe72 once cbor is fixed.
"baf9eeaa4860e363a9c27d99555839afc535f0cd32d23dc640f0f020677460e0",
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/keymanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/keymanager/churp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
47 changes: 44 additions & 3 deletions runtime/src/consensus/state/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,15 @@ impl<'a, T: ImmutableMKVS> ImmutableState<'a, T> {

#[cfg(test)]
mod test {
use std::collections::BTreeMap;

use crate::{
common::crypto::signature,
consensus::registry::{
Capabilities, CapabilityTEE, ConsensusInfo, NodeRuntime, P2PInfo, RuntimeKind,
TEEHardware, TLSInfo, VRFInfo, VersionInfo,
AnyNodeRuntimeAdmissionPolicy, Capabilities, CapabilityTEE, ConsensusInfo,
EntityWhitelistRoleAdmissionPolicy, NodeRuntime, P2PInfo, PerRoleAdmissionPolicy,
RolesMask, RuntimeAdmissionPolicy, RuntimeKind, TEEHardware, TLSInfo, VRFInfo,
VersionInfo,
},
storage::mkvs::{
interop::{Fixture, ProtocolServer},
Expand All @@ -128,7 +132,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down Expand Up @@ -221,6 +225,10 @@ mod test {
),
kind: RuntimeKind::KindCompute,
tee_hardware: TEEHardware::TEEHardwareInvalid,
admission_policy: RuntimeAdmissionPolicy {
any_node: Some(AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
deployments: vec![
VersionInfo {
version: Version::from(321),
Expand All @@ -245,6 +253,10 @@ mod test {
),
kind: RuntimeKind::KindCompute,
tee_hardware: TEEHardware::TEEHardwareIntelSGX,
admission_policy: RuntimeAdmissionPolicy {
any_node: Some(AnyNodeRuntimeAdmissionPolicy {}),
..Default::default()
},
deployments: vec![
VersionInfo {
version: Version::from(123),
Expand All @@ -261,6 +273,35 @@ mod test {
],
..Default::default()
},
Runtime {
v: 3,
id: Namespace::from(
"8000000000000000000000000000000000000000000000000000000000000012",
),
entity_id: signature::PublicKey::from(
"761950dfe65936f6e9d06a0124bc930f7d5b1812ceefdfb2cae0ef5841291531",
),
kind: RuntimeKind::KindCompute,
tee_hardware: TEEHardware::TEEHardwareIntelSGX,
admission_policy: RuntimeAdmissionPolicy {
per_role: BTreeMap::from([(
RolesMask::ROLE_OBSERVER,
PerRoleAdmissionPolicy {
entity_whitelist: Some(EntityWhitelistRoleAdmissionPolicy {
entities: BTreeMap::new(),
}),
},
)]),
..Default::default()
},
deployments: vec![VersionInfo {
version: Version::from(123),
valid_from: 42,
tee: vec![1, 2, 3, 4, 5],
bundle_checksum: vec![0x5; 32],
}],
..Default::default()
},
];

for rt in expected_runtimes {
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/roothash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("280a0d815030421f16366da7cc57efbfc7fc87d9a7d16964216c79873ebd240a"),
hash: Hash::from("1c2ce324ac7d7b3a5f47cc73fed9455b96d562c2488250f28af8101fe2e32cb3"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down

0 comments on commit 30968d6

Please sign in to comment.