From aa1cc769da3142a6e1aa0ecd12a007413b94f77c Mon Sep 17 00:00:00 2001 From: brenzi Date: Sat, 23 Dec 2023 07:24:47 +0100 Subject: [PATCH] root can purge enclave from shard config (#238) * accept any new sidechain block from authorized enclave for shard * introduce purge_enclave_from_shard_status and make ShardStatus a BoundedVec * tests passed * add Event check * review comments and fix bogus test --- Cargo.lock | 80 ++++++------ enclave-bridge/src/lib.rs | 98 ++++++++++----- enclave-bridge/src/tests/mod.rs | 2 + enclave-bridge/src/tests/test_shard_status.rs | 119 ++++++++++++++++++ enclave-bridge/src/weights.rs | 12 ++ primitives/enclave-bridge/src/lib.rs | 1 + 6 files changed, 243 insertions(+), 69 deletions(-) create mode 100644 enclave-bridge/src/tests/test_shard_status.rs diff --git a/Cargo.lock b/Cargo.lock index 03d55acd..4f7718c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-support-procedural", @@ -910,7 +910,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bitflags 1.3.2", "environmental", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "cfg-expr", @@ -959,7 +959,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", @@ -981,7 +981,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "log", @@ -1786,7 +1786,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -1955,7 +1955,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -1973,7 +1973,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -2813,7 +2813,7 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -2833,7 +2833,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "blake2", @@ -2847,7 +2847,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -2860,7 +2860,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "integer-sqrt", "num-traits", @@ -2874,7 +2874,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -2887,7 +2887,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -2899,7 +2899,7 @@ dependencies = [ [[package]] name = "sp-core" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes", "bitflags 1.3.2", @@ -2943,7 +2943,7 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "blake2b_simd", "byteorder", @@ -2957,7 +2957,7 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", @@ -2968,7 +2968,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", @@ -2978,7 +2978,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "environmental", "parity-scale-codec", @@ -2989,7 +2989,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -3004,7 +3004,7 @@ dependencies = [ [[package]] name = "sp-io" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "ed25519", @@ -3030,7 +3030,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lazy_static", "sp-core", @@ -3041,7 +3041,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "parity-scale-codec", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "sp-metadata-ir" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -3066,7 +3066,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "backtrace", "lazy_static", @@ -3076,7 +3076,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "either", "hash256-std-hasher", @@ -3098,7 +3098,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -3116,7 +3116,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "proc-macro-crate", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -3141,7 +3141,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -3161,12 +3161,12 @@ dependencies = [ [[package]] name = "sp-std" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" [[package]] name = "sp-storage" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -3179,7 +3179,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures-timer", @@ -3194,7 +3194,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-std", @@ -3206,7 +3206,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.6", "hash-db", @@ -3229,7 +3229,7 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -3246,7 +3246,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -3257,7 +3257,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -3271,7 +3271,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/enclave-bridge/src/lib.rs b/enclave-bridge/src/lib.rs index 750b558b..5e533ebc 100644 --- a/enclave-bridge/src/lib.rs +++ b/enclave-bridge/src/lib.rs @@ -17,33 +17,35 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use crate::weights::WeightInfo; use codec::Encode; -use enclave_bridge_primitives::*; +use enclave_bridge_primitives::{ + Request, ShardConfig, ShardIdentifier, ShardSignerStatus as ShardSignerStatusGeneric, + UpgradableShardConfig, ENCLAVE_BRIDGE, MAX_SHARD_STATUS_SIGNER_COUNT, +}; use frame_support::{ dispatch::{DispatchErrorWithPostInfo, DispatchResult, DispatchResultWithPostInfo}, ensure, + pallet_prelude::ConstU32, traits::{Currency, ExistenceRequirement}, }; use frame_system::{self, ensure_signed}; -use sp_core::H256; +use pallet_teerex::Pallet as Teerex; +use sp_core::{bounded::BoundedVec, H256}; use sp_runtime::traits::{SaturatedConversion, Saturating}; use sp_std::{prelude::*, str, vec}; - -pub use crate::weights::WeightInfo; - +use teerex_primitives::{EnclaveFingerprint, MultiEnclave}; // Disambiguate associated types pub type AccountId = ::AccountId; pub type BalanceOf = <::Currency as Currency>>::Balance; -pub type ShardSignerStatusVec = Vec< - ShardSignerStatus< - ::AccountId, - ::BlockNumber, - >, +pub type ShardSignerStatus = ShardSignerStatusGeneric< + ::AccountId, + ::BlockNumber, >; +pub type ShardSignerStatusVec = + BoundedVec, ConstU32>; pub use pallet::*; -use pallet_teerex::Pallet as Teerex; -use teerex_primitives::MultiEnclave; /// Maximum number of topics for the `publish_hash` call. const TOPICS_LIMIT: usize = 5; @@ -101,6 +103,11 @@ pub mod pallet { data: Vec, }, ShardConfigUpdated(ShardIdentifier), + /// An enclave has been purged from a shard status. Most likely due to inactivity + PurgedEnclaveFromShardConfig { + shard: ShardIdentifier, + subject: T::AccountId, + }, } #[pallet::error] @@ -111,17 +118,18 @@ pub mod pallet { TooManyTopics, /// The length of the `data` passed to `publish_hash` exceeds the limit. DataTooLong, + /// Too many enclaves in ShardStatus + TooManyEnclaves, + /// No such enclave was found in shard status + EnclaveNotFoundInShardStatus, + /// Shard not found + ShardNotFound, } #[pallet::storage] #[pallet::getter(fn shard_status)] - pub type ShardStatus = StorageMap< - _, - Blake2_128Concat, - ShardIdentifier, - Vec>, - OptionQuery, - >; + pub type ShardStatus = + StorageMap<_, Blake2_128Concat, ShardIdentifier, ShardSignerStatusVec, OptionQuery>; /// this registry holds shard configurations as well as pending updates thereof. /// We decided to put config and update data in the same storage for performance reasons. @@ -362,6 +370,40 @@ pub mod pallet { Self::deposit_event(Event::ShardConfigUpdated(shard)); Ok(().into()) } + /// Purge enclave from shard status + /// this is a root call to be used for maintenance. Shall eventually be replaced by a lazy timeout + #[pallet::call_index(6)] + #[pallet::weight((::WeightInfo::purge_enclave_from_shard_status(), DispatchClass::Normal, Pays::No))] + pub fn purge_enclave_from_shard_status( + origin: OriginFor, + shard: ShardIdentifier, + subject: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + + let new_status: ShardSignerStatusVec = Self::shard_status(shard) + .ok_or(Error::::ShardNotFound)? + .iter() + .cloned() + .filter(|signer_status| signer_status.signer != subject) + .collect::>>() + .try_into() + .expect("can only become smaller by filtering"); + + >::insert(shard, new_status); + + log::info!( + target: ENCLAVE_BRIDGE, + "purged {:?} from shard status for {:?}", + subject, + shard, + ); + Self::deposit_event(crate::pallet::Event::PurgedEnclaveFromShardConfig { + shard, + subject, + }); + Ok(().into()) + } } } @@ -371,10 +413,7 @@ impl Pallet { enclave_signer: &T::AccountId, shard: ShardIdentifier, current_block_number: T::BlockNumber, - ) -> Result< - (MultiEnclave>, Vec>), - DispatchErrorWithPostInfo, - > { + ) -> Result<(MultiEnclave>, ShardSignerStatusVec), DispatchErrorWithPostInfo> { let enclave = Teerex::::get_sovereign_enclave(enclave_signer)?; ensure!( enclave.fingerprint() == @@ -418,14 +457,15 @@ impl Pallet { enclave_fingerprint: EnclaveFingerprint, current_block_number: T::BlockNumber, ) -> Result, DispatchErrorWithPostInfo> { - let new_status = ShardSignerStatus { + let new_status = ShardSignerStatus:: { signer: enclave_signer.clone(), fingerprint: enclave_fingerprint, last_activity: current_block_number, }; - let signer_statuses = >::get(shard) - .map(|mut status_vec| { + let signer_statuses: Vec> = Self::shard_status(shard) + .map(|status_bvec| { + let mut status_vec = status_bvec.to_vec(); if let Some(index) = status_vec.iter().position(|i| &i.signer == enclave_signer) { status_vec[index] = new_status.clone(); } else { @@ -435,6 +475,8 @@ impl Pallet { }) .unwrap_or_else(|| vec![new_status]); + let signer_statuses = ShardSignerStatusVec::::try_from(signer_statuses) + .map_err(|_| Error::::TooManyEnclaves)?; log::trace!( target: ENCLAVE_BRIDGE, "touched shard: {:?}, signer statuses: {:?}", @@ -445,9 +487,7 @@ impl Pallet { Ok(signer_statuses) } - pub fn most_recent_shard_update( - shard: &ShardIdentifier, - ) -> Option> { + pub fn most_recent_shard_update(shard: &ShardIdentifier) -> Option> { >::get(shard) .map(|mut statuses| { statuses.sort_by_key(|a| a.last_activity); diff --git a/enclave-bridge/src/tests/mod.rs b/enclave-bridge/src/tests/mod.rs index d50dc0e3..fcdc8c10 100644 --- a/enclave-bridge/src/tests/mod.rs +++ b/enclave-bridge/src/tests/mod.rs @@ -25,6 +25,8 @@ mod test_indirect_invocation; mod test_publish_hash; mod test_shard_config; +mod test_shard_status; + fn get_bonding_account(enclave: &MultiEnclave>) -> AccountId { AccountId::decode(&mut enclave.fingerprint().encode().as_ref()).unwrap() } diff --git a/enclave-bridge/src/tests/test_shard_status.rs b/enclave-bridge/src/tests/test_shard_status.rs new file mode 100644 index 00000000..2ad5293a --- /dev/null +++ b/enclave-bridge/src/tests/test_shard_status.rs @@ -0,0 +1,119 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::*; +use crate::{Error, Event as EnclaveBridgeEvent, ShardConfigRegistry}; +use enclave_bridge_primitives::{ShardConfig, ShardIdentifier, UpgradableShardConfig}; +use frame_support::{assert_err, assert_noop, assert_ok}; +use sp_keyring::AccountKeyring; +use teerex_primitives::EnclaveFingerprint; + +#[test] +fn purge_enclave_from_shard_status_works_if_present() { + new_test_ext().execute_with(|| { + Timestamp::set_timestamp(NOW); + let enclave_signer_1 = AccountKeyring::Eve.to_account_id(); + let enclave_signer_2 = AccountKeyring::Ferdie.to_account_id(); + let enclave_fingerprint = EnclaveFingerprint::default(); + let shard = ShardIdentifier::default(); + assert_ok!(EnclaveBridge::touch_shard( + shard, + &enclave_signer_1.clone(), + enclave_fingerprint, + 1 + )); + assert_ok!(EnclaveBridge::purge_enclave_from_shard_status( + RuntimeOrigin::root(), + shard, + enclave_signer_1.clone(), + )); + let expected_event = + RuntimeEvent::EnclaveBridge(EnclaveBridgeEvent::PurgedEnclaveFromShardConfig { + shard, + subject: enclave_signer_1.clone(), + }); + println!("events:{:?}", System::events()); + assert!(System::events().iter().any(|a| a.event == expected_event)); + + assert!(EnclaveBridge::shard_status(shard).is_some()); + assert_eq!(EnclaveBridge::shard_status(shard).unwrap().len(), 0); + assert_ok!(EnclaveBridge::touch_shard( + shard, + &enclave_signer_1.clone(), + enclave_fingerprint, + 2 + )); + assert_ok!(EnclaveBridge::touch_shard( + shard, + &enclave_signer_2.clone(), + enclave_fingerprint, + 2 + )); + assert!(EnclaveBridge::shard_status(shard).is_some()); + assert_eq!(EnclaveBridge::shard_status(shard).unwrap().len(), 2); + + assert_ok!(EnclaveBridge::purge_enclave_from_shard_status( + RuntimeOrigin::root(), + shard, + enclave_signer_1, + )); + + assert!(EnclaveBridge::shard_status(shard).is_some()); + assert_eq!(EnclaveBridge::shard_status(shard).unwrap().len(), 1); + assert_eq!(EnclaveBridge::shard_status(shard).unwrap()[0].signer, enclave_signer_2); + }) +} + +#[test] +fn purge_enclave_from_shard_status_for_inexistent_shard_is_err() { + new_test_ext().execute_with(|| { + Timestamp::set_timestamp(NOW); + let enclave_signer_1 = AccountKeyring::Eve.to_account_id(); + let shard = ShardIdentifier::default(); + + assert_noop!( + EnclaveBridge::purge_enclave_from_shard_status( + RuntimeOrigin::root(), + shard, + enclave_signer_1.clone(), + ), + Error::::ShardNotFound + ); + }) +} + +#[test] +fn purge_enclave_from_shard_status_fails_if_not_root() { + new_test_ext().execute_with(|| { + Timestamp::set_timestamp(NOW); + let enclave_signer_1 = AccountKeyring::Eve.to_account_id(); + let enclave_fingerprint = EnclaveFingerprint::default(); + let shard = ShardIdentifier::default(); + assert_ok!(EnclaveBridge::touch_shard( + shard, + &enclave_signer_1.clone(), + enclave_fingerprint, + 1 + )); + assert!(EnclaveBridge::purge_enclave_from_shard_status( + RuntimeOrigin::signed(enclave_signer_1.clone()), + shard, + enclave_signer_1.clone(), + ) + .is_err()); + }) +} diff --git a/enclave-bridge/src/weights.rs b/enclave-bridge/src/weights.rs index c113d43c..5b2aca7d 100644 --- a/enclave-bridge/src/weights.rs +++ b/enclave-bridge/src/weights.rs @@ -56,6 +56,7 @@ pub trait WeightInfo { fn unshield_funds() -> Weight; fn publish_hash(l: u32, t: u32) -> Weight; fn update_shard_config() -> Weight; + fn purge_enclave_from_shard_status() -> Weight; } /// Weights for pallet_teerex using the Integritee parachain node and recommended hardware. @@ -129,6 +130,12 @@ impl WeightInfo for IntegriteeWeight { .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } + + fn purge_enclave_from_shard_status() -> Weight { + Weight::from_parts(10_000_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } /// For tests, weights have been generated with the integritee-node. @@ -196,4 +203,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3)) .saturating_add(RocksDbWeight::get().writes(2)) } + fn purge_enclave_from_shard_status() -> Weight { + Weight::from_parts(10_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) + } } diff --git a/primitives/enclave-bridge/src/lib.rs b/primitives/enclave-bridge/src/lib.rs index 7fb258da..741f9dbe 100644 --- a/primitives/enclave-bridge/src/lib.rs +++ b/primitives/enclave-bridge/src/lib.rs @@ -36,6 +36,7 @@ pub struct ShardSignerStatus { pub fingerprint: EnclaveFingerprint, pub last_activity: BlockNumber, } +pub const MAX_SHARD_STATUS_SIGNER_COUNT: u32 = 10; #[derive(Encode, Decode, Clone, PartialEq, Eq, sp_core::RuntimeDebug, TypeInfo)] pub struct ShardConfig {