From f286071948a1c1f4de398bd44840e11ee36cc740 Mon Sep 17 00:00:00 2001 From: peg Date: Wed, 25 Sep 2024 10:51:15 +0200 Subject: [PATCH] Handle Provisioning Certification Keys (PCKs) (#1051) * Add PCK to server info * Add PCK to chainspec * Update chainspec genesis config to include PCKs for all TSSs * Add sp-runtime to wasm deps of entropy-shared * Bump tdx-quote, check PCK signature when verifying quotes * Update benchmarks * When mocking, derive PCK from TSS account id * Get boundedvec from sp-core, not sp-runtime * Ignore BoundedVec type when compiling for wasm with std * Update propagation pallet mock * Update attestation pallet mock * Add helpers for deriving mock pcks * Add actual PCK values to chainspec * Rm unused import * Update registry tests * Update metadata * Comments * Fix client test * Add random secret PCK to attestation pallet benchmark test * Fix attestation benchmark * Fix attestation benchmark again * Update attestation pallet test * Fix attestation pallet mock/bench * Fix entropy-client test * Fix client test * Fix client test * Changelog * Rm unused dependency from staking pallet --- CHANGELOG.md | 1 + Cargo.lock | 4 +- crates/client/entropy_metadata.scale | Bin 208617 -> 208772 bytes crates/client/src/tests.rs | 16 +++- crates/shared/src/types.rs | 4 + crates/testing-utils/Cargo.toml | 1 + crates/testing-utils/src/helpers.rs | 19 +++- crates/threshold-signature-server/Cargo.toml | 5 +- .../src/attestation/api.rs | 9 +- node/cli/src/chain_spec/dev.rs | 33 +++++-- node/cli/src/chain_spec/integration_tests.rs | 6 +- node/cli/src/chain_spec/mod.rs | 29 ++++++ node/cli/src/chain_spec/testnet.rs | 29 ++++-- pallets/attestation/Cargo.toml | 4 +- pallets/attestation/src/benchmarking.rs | 19 +++- pallets/attestation/src/lib.rs | 34 ++++--- pallets/attestation/src/mock.rs | 13 ++- pallets/attestation/src/tests.rs | 7 +- pallets/propagation/src/mock.rs | 12 +-- pallets/registry/src/benchmarking.rs | 8 +- pallets/registry/src/mock.rs | 12 +-- pallets/registry/src/tests.rs | 24 +++-- pallets/staking/src/benchmarking.rs | 11 ++- pallets/staking/src/lib.rs | 4 +- pallets/staking/src/mock.rs | 7 +- pallets/staking/src/tests.rs | 88 ++++++++++++++---- 26 files changed, 304 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8148a6b6..22baf545b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ At the moment this project **does not** adhere to - Add remove program function to entropy-client ([#1023](https://github.com/entropyxyz/entropy-core/pull/1023)) - Select validators for jumpstart DKG [#1053](https://github.com/entropyxyz/entropy-core/pull/1053)) - Add a programs version ([#1045](https://github.com/entropyxyz/entropy-core/pull/1045)) +- Handle Provisioning Certification Keys (PCKs) ([#1051](https://github.com/entropyxyz/entropy-core/pull/1051)) ### Changed - Fix TSS `AccountId` keys in chainspec ([#993](https://github.com/entropyxyz/entropy-core/pull/993)) diff --git a/Cargo.lock b/Cargo.lock index 29006b9d5..47bbaeff3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2751,6 +2751,7 @@ dependencies = [ "sp-keyring 34.0.0", "subxt", "synedrion", + "tdx-quote", "tokio", "tracing", "tracing-subscriber 0.3.18", @@ -2789,6 +2790,7 @@ dependencies = [ "num", "parity-scale-codec", "project-root", + "rand", "rand_core 0.6.4", "reqwest", "reqwest-eventsource", @@ -14138,7 +14140,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tdx-quote" version = "0.1.0" -source = "git+https://github.com/entropyxyz/tdx-quote?rev=f7968ff#f7968ff35ff744ff8c007cffe6ec8d709d7f18d9" +source = "git+https://github.com/entropyxyz/tdx-quote?rev=cb167f2#cb167f2aef1c7539c91082ee21c764eac60f6bef" dependencies = [ "nom", "p256", diff --git a/crates/client/entropy_metadata.scale b/crates/client/entropy_metadata.scale index adb357cc3bf70dcb346378a9c6eacde1e3df61f1..3c2856de606a1c8b1dd9303eb79fa3fcaf95cc33 100644 GIT binary patch delta 3101 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 diff --git a/crates/client/src/tests.rs b/crates/client/src/tests.rs index 0315cdb5e..13ab41d8d 100644 --- a/crates/client/src/tests.rs +++ b/crates/client/src/tests.rs @@ -16,8 +16,11 @@ use crate::{ update_programs, }; use entropy_testing_utils::{ - constants::TEST_PROGRAM_WASM_BYTECODE, jump_start_network, - substrate_context::test_context_stationary, test_node_process_testing_state, + constants::{TEST_PROGRAM_WASM_BYTECODE, TSS_ACCOUNTS}, + helpers::{derive_mock_pck_verifying_key, encode_verifying_key}, + jump_start_network, + substrate_context::test_context_stationary, + test_node_process_testing_state, }; use serial_test::serial; use sp_core::{sr25519, Pair, H256}; @@ -64,6 +67,12 @@ async fn test_change_threshold_accounts() { ) .await .unwrap(); + + let provisioning_certification_key = { + let key = derive_mock_pck_verifying_key(&TSS_ACCOUNTS[0]); + BoundedVec(encode_verifying_key(&key).unwrap().to_vec()) + }; + assert_eq!( format!("{:?}", result), format!( @@ -73,7 +82,8 @@ async fn test_change_threshold_accounts() { ServerInfo { tss_account: AccountId32(one.pair().public().0), x25519_public_key, - endpoint: "127.0.0.1:3001".as_bytes().to_vec() + endpoint: "127.0.0.1:3001".as_bytes().to_vec(), + provisioning_certification_key, } ) ) diff --git a/crates/shared/src/types.rs b/crates/shared/src/types.rs index 48a5ab089..0cf844dd3 100644 --- a/crates/shared/src/types.rs +++ b/crates/shared/src/types.rs @@ -109,6 +109,10 @@ pub enum HashingAlgorithm { /// A compressed, serialized [synedrion::ecdsa::VerifyingKey] pub type EncodedVerifyingKey = [u8; VERIFICATION_KEY_LENGTH as usize]; +#[cfg(not(feature = "wasm"))] +pub type BoundedVecEncodedVerifyingKey = + sp_runtime::BoundedVec>; + /// Input data to be included in a TDX attestation pub struct QuoteInputData(pub [u8; 64]); diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index c1c955751..9cf8ae52d 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -26,6 +26,7 @@ synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="1d210d1 hex ="0.4.3" rand_core ="0.6.4" rand ="0.8.5" +tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", features=["mock"] } # Logging tracing ="0.1.37" diff --git a/crates/testing-utils/src/helpers.rs b/crates/testing-utils/src/helpers.rs index 60194a153..5e64f843e 100644 --- a/crates/testing-utils/src/helpers.rs +++ b/crates/testing-utils/src/helpers.rs @@ -20,7 +20,9 @@ use crate::{ ChainSpecType, }; use entropy_protocol::PartyId; -use subxt::{backend::legacy::LegacyRpcMethods, OnlineClient}; +use rand::{rngs::StdRng, SeedableRng}; +use subxt::{backend::legacy::LegacyRpcMethods, utils::AccountId32, OnlineClient}; +pub use tdx_quote::encode_verifying_key; /// A helper for setting up tests which starts both a set of TS servers and a chain node and returns /// the chain API as well as IP addresses and PartyId of the started validators @@ -52,3 +54,18 @@ pub async fn spawn_tss_nodes_and_start_chain( }; (api, rpc, validator_ips, validator_ids) } + +/// Get the mock PCK that will be used for a given TSS account ID +pub fn derive_mock_pck_verifying_key(tss_account_id: &AccountId32) -> tdx_quote::VerifyingKey { + let mut pck_seeder = StdRng::from_seed(tss_account_id.0); + let pck = tdx_quote::SigningKey::random(&mut pck_seeder); + tdx_quote::VerifyingKey::from(pck) +} + +/// For each test TSS account, display the encoded mock PCK +pub fn print_test_pck_verifying_keys() { + for tss_account in crate::constants::TSS_ACCOUNTS.iter() { + let pck = derive_mock_pck_verifying_key(tss_account); + println!("{:?}", encode_verifying_key(&pck)); + } +} diff --git a/crates/threshold-signature-server/Cargo.toml b/crates/threshold-signature-server/Cargo.toml index 95cf52549..e8f20d734 100644 --- a/crates/threshold-signature-server/Cargo.toml +++ b/crates/threshold-signature-server/Cargo.toml @@ -17,6 +17,7 @@ thiserror ="1.0.64" blake2 ="0.10.4" x25519-dalek ={ version="2.0.1", features=["static_secrets"] } rand_core ="0.6.4" +rand ="0.8.5" zeroize ="1.8.1" hex ="0.4.3" reqwest-eventsource="0.6" @@ -71,7 +72,7 @@ sha1="0.10.6" sha2="0.10.8" hkdf="0.12.4" project-root={ version="0.2.2", optional=true } -tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff", optional=true, features=[ +tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", optional=true, features=[ "mock", ] } configfs-tsm={ git="https://github.com/entropyxyz/configfs-tsm", rev="f32c166", optional=true } @@ -88,7 +89,7 @@ ethers-core ="2.0.14" schnorrkel ={ version="0.11.4", default-features=false, features=["std"] } schemars ={ version="0.8.21" } subxt-signer="0.35.3" -tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff", features=["mock"] } +tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", features=["mock"] } # Note: We don't specify versions here because otherwise we run into a cyclical dependency between # `entropy-tss` and `entropy-testing-utils` when we try and publish the `entropy-tss` crate. diff --git a/crates/threshold-signature-server/src/attestation/api.rs b/crates/threshold-signature-server/src/attestation/api.rs index 918d3c7e1..8615e4e6a 100644 --- a/crates/threshold-signature-server/src/attestation/api.rs +++ b/crates/threshold-signature-server/src/attestation/api.rs @@ -78,10 +78,11 @@ pub async fn create_quote( signer: &PairSigner, x25519_secret: &StaticSecret, ) -> Result, AttestationErr> { + use rand::{rngs::StdRng, SeedableRng}; use rand_core::OsRng; use sp_core::Pair; - // In the real thing this is the hardware key used in the quoting enclave + // In the real thing this is the key used in the quoting enclave let signing_key = tdx_quote::SigningKey::random(&mut OsRng); let public_key = x25519_dalek::PublicKey::from(x25519_secret); @@ -93,7 +94,11 @@ pub async fn create_quote( block_number, ); - let quote = tdx_quote::Quote::mock(signing_key.clone(), input_data.0).as_bytes().to_vec(); + // This is generated deterministically from TSS account id + let mut pck_seeder = StdRng::from_seed(signer.signer().public().0); + let pck = tdx_quote::SigningKey::random(&mut pck_seeder); + + let quote = tdx_quote::Quote::mock(signing_key.clone(), pck, input_data.0).as_bytes().to_vec(); Ok(quote) } diff --git a/node/cli/src/chain_spec/dev.rs b/node/cli/src/chain_spec/dev.rs index 5f33a1b44..6e6aaa186 100644 --- a/node/cli/src/chain_spec/dev.rs +++ b/node/cli/src/chain_spec/dev.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use crate::chain_spec::{get_account_id_from_seed, ChainSpec}; +use crate::chain_spec::{get_account_id_from_seed, provisioning_certification_key, ChainSpec}; use crate::endowed_accounts::endowed_accounts_dev; use entropy_runtime::{ @@ -24,9 +24,9 @@ use entropy_runtime::{ }; use entropy_runtime::{AccountId, Balance}; use entropy_shared::{ - X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE, DEVICE_KEY_CONFIG_TYPE, - DEVICE_KEY_HASH, DEVICE_KEY_PROXY, INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD, - TOTAL_SIGNERS, + BoundedVecEncodedVerifyingKey, X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE, + DEVICE_KEY_CONFIG_TYPE, DEVICE_KEY_HASH, DEVICE_KEY_PROXY, + INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD, TOTAL_SIGNERS, }; use grandpa_primitives::AuthorityId as GrandpaId; use itertools::Itertools; @@ -38,75 +38,85 @@ use sp_core::{sr25519, ByteArray}; use sp_runtime::{BoundedVec, Perbill}; pub fn devnet_three_node_initial_tss_servers( -) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> { +) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> { let alice = ( crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_x25519_public_key::ALICE, "127.0.0.1:3001".to_string(), + provisioning_certification_key::ALICE.clone(), ); let bob = ( crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_x25519_public_key::BOB, "127.0.0.1:3002".to_string(), + provisioning_certification_key::BOB.clone(), ); let charlie = ( crate::chain_spec::tss_account_id::CHARLIE.clone(), crate::chain_spec::tss_x25519_public_key::CHARLIE, "127.0.0.1:3003".to_string(), + provisioning_certification_key::CHARLIE.clone(), ); vec![alice, bob, charlie] } pub fn devnet_local_docker_three_node_initial_tss_servers( -) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> { +) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> { let alice = ( crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_x25519_public_key::ALICE, "alice-tss-server:3001".to_string(), + provisioning_certification_key::ALICE.clone(), ); let bob = ( crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_x25519_public_key::BOB, "bob-tss-server:3002".to_string(), + provisioning_certification_key::BOB.clone(), ); let charlie = ( crate::chain_spec::tss_account_id::CHARLIE.clone(), crate::chain_spec::tss_x25519_public_key::CHARLIE, "charlie-tss-server:3003".to_string(), + provisioning_certification_key::CHARLIE.clone(), ); vec![alice, bob, charlie] } pub fn devnet_local_docker_four_node_initial_tss_servers( -) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)> { +) -> Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String, BoundedVecEncodedVerifyingKey)> { let alice = ( crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_x25519_public_key::ALICE, "alice-tss-server:3001".to_string(), + provisioning_certification_key::ALICE.clone(), ); let bob = ( crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_x25519_public_key::BOB, "bob-tss-server:3002".to_string(), + provisioning_certification_key::BOB.clone(), ); let dave = ( crate::chain_spec::tss_account_id::DAVE.clone(), crate::chain_spec::tss_x25519_public_key::DAVE, "dave-tss-server:3003".to_string(), + provisioning_certification_key::DAVE.clone(), ); let eve = ( crate::chain_spec::tss_account_id::EVE.clone(), crate::chain_spec::tss_x25519_public_key::EVE_TSS, "eve-tss-server:3004".to_string(), + provisioning_certification_key::EVE.clone(), ); vec![alice, bob, dave, eve] @@ -194,7 +204,12 @@ pub fn development_genesis_config( )>, initial_nominators: Vec, root_key: AccountId, - initial_tss_servers: Vec<(sp_runtime::AccountId32, TssX25519PublicKey, String)>, + initial_tss_servers: Vec<( + sp_runtime::AccountId32, + TssX25519PublicKey, + String, + BoundedVecEncodedVerifyingKey, + )>, ) -> serde_json::Value { // Note that any endowed_accounts added here will be included in the `elections` and // `technical_committee` genesis configs. If you don't want that, don't push those accounts to @@ -272,7 +287,7 @@ pub fn development_genesis_config( .iter() .zip(initial_tss_servers.iter()) .map(|(auth, tss)| { - (auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec())) + (auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec(), tss.3.clone())) }) .collect::>(), proactive_refresh_data: (vec![], vec![]), diff --git a/node/cli/src/chain_spec/integration_tests.rs b/node/cli/src/chain_spec/integration_tests.rs index b45dfe5de..5d7fc54ed 100644 --- a/node/cli/src/chain_spec/integration_tests.rs +++ b/node/cli/src/chain_spec/integration_tests.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use crate::chain_spec::{get_account_id_from_seed, ChainSpec}; +use crate::chain_spec::{get_account_id_from_seed, provisioning_certification_key, ChainSpec}; use crate::endowed_accounts::endowed_accounts_dev; use entropy_runtime::{ @@ -158,6 +158,7 @@ pub fn integration_tests_genesis_config( crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_x25519_public_key::ALICE, "127.0.0.1:3001".as_bytes().to_vec(), + provisioning_certification_key::ALICE.clone(), ), ), ( @@ -166,6 +167,7 @@ pub fn integration_tests_genesis_config( crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_x25519_public_key::BOB, "127.0.0.1:3002".as_bytes().to_vec(), + provisioning_certification_key::BOB.clone(), ), ), ( @@ -174,6 +176,7 @@ pub fn integration_tests_genesis_config( crate::chain_spec::tss_account_id::CHARLIE.clone(), crate::chain_spec::tss_x25519_public_key::CHARLIE, "127.0.0.1:3003".as_bytes().to_vec(), + provisioning_certification_key::CHARLIE.clone(), ), ), ( @@ -182,6 +185,7 @@ pub fn integration_tests_genesis_config( crate::chain_spec::tss_account_id::DAVE.clone(), crate::chain_spec::tss_x25519_public_key::DAVE, "127.0.0.1:3004".as_bytes().to_vec(), + provisioning_certification_key::DAVE.clone(), ), ), ], diff --git a/node/cli/src/chain_spec/mod.rs b/node/cli/src/chain_spec/mod.rs index 79485d720..ed9f3c9cd 100644 --- a/node/cli/src/chain_spec/mod.rs +++ b/node/cli/src/chain_spec/mod.rs @@ -126,6 +126,35 @@ pub mod tss_x25519_public_key { ]; } +/// Mock provisioning certification keys for attestation of the test TS servers. +/// These are generated deterministically from their TSS account IDs using the helper function +/// entropy_testing_utils::helpers::print_test_pck_verifying_keys +pub mod provisioning_certification_key { + use entropy_shared::BoundedVecEncodedVerifyingKey; + + lazy_static::lazy_static! { + pub static ref ALICE: BoundedVecEncodedVerifyingKey = vec![ + 2, 137, 55, 65, 52, 103, 166, 204, 247, 160, 46, 220, 5, 113, 151, 217, 157, 196, 11, + 240, 175, 82, 148, 230, 31, 245, 207, 194, 3, 74, 121, 184, 20 + ].try_into().unwrap(); + pub static ref BOB: BoundedVecEncodedVerifyingKey = vec![ + 3, 83, 163, 234, 166, 114, 67, 146, 122, 122, 99, 236, 205, 116, 209, 45, 230, 107, 62, + 55, 147, 38, 185, 203, 157, 147, 156, 173, 233, 58, 134, 162, 156].try_into().unwrap(); + pub static ref CHARLIE: BoundedVecEncodedVerifyingKey = vec![ + 2, 167, 50, 42, 76, 239, 190, 42, 72, 64, 110, 90, 172, 253, 252, 148, 115, 107, 34, 110, + 2, 112, 184, 147, 87, 71, 63, 217, 238, 89, 253, 97, 176 + ].try_into().unwrap(); + pub static ref DAVE: BoundedVecEncodedVerifyingKey = vec![ + 3, 68, 52, 130, 44, 84, 174, 32, 55, 213, 192, 7, 121, 188, 19, 231, 134, 47, 223, 166, + 199, 118, 161, 203, 142, 75, 184, 108, 165, 70, 251, 249, 142 + ].try_into().unwrap(); + pub static ref EVE: BoundedVecEncodedVerifyingKey = vec![ + 2, 60, 115, 185, 180, 118, 177, 23, 3, 49, 65, 92, 230, 60, 245, 1, 140, 149, 117, 238, + 83, 69, 110, 30, 140, 31, 60, 69, 38, 34, 202, 242, 125 + ].try_into().unwrap(); + } +} + fn entropy_properties() -> Properties { json!({"tokenDecimals": 10, "tokenSymbol": "BITS" }).as_object().unwrap().clone() } diff --git a/node/cli/src/chain_spec/testnet.rs b/node/cli/src/chain_spec/testnet.rs index fb5848420..9dd3c1f5f 100644 --- a/node/cli/src/chain_spec/testnet.rs +++ b/node/cli/src/chain_spec/testnet.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use crate::chain_spec::{get_account_id_from_seed, ChainSpec}; +use crate::chain_spec::{get_account_id_from_seed, provisioning_certification_key, ChainSpec}; use crate::endowed_accounts::endowed_testnet_accounts; use entropy_runtime::{ @@ -24,9 +24,9 @@ use entropy_runtime::{ }; use entropy_runtime::{AccountId, Balance}; use entropy_shared::{ - X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE, DEVICE_KEY_CONFIG_TYPE, - DEVICE_KEY_HASH, DEVICE_KEY_PROXY, INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD, - TOTAL_SIGNERS, + BoundedVecEncodedVerifyingKey, X25519PublicKey as TssX25519PublicKey, DEVICE_KEY_AUX_DATA_TYPE, + DEVICE_KEY_CONFIG_TYPE, DEVICE_KEY_HASH, DEVICE_KEY_PROXY, + INITIAL_MAX_INSTRUCTIONS_PER_PROGRAM, SIGNER_THRESHOLD, TOTAL_SIGNERS, }; use grandpa_primitives::AuthorityId as GrandpaId; use hex_literal::hex; @@ -177,17 +177,20 @@ pub fn testnet_local_config() -> crate::chain_spec::ChainSpec { .build() } -pub fn testnet_local_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, TssEndpoint)> { +pub fn testnet_local_initial_tss_servers( +) -> Vec<(TssAccountId, TssX25519PublicKey, TssEndpoint, BoundedVecEncodedVerifyingKey)> { let alice = ( crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_x25519_public_key::ALICE, "alice-tss-server:3001".to_string(), + provisioning_certification_key::ALICE.clone(), ); let bob = ( crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_x25519_public_key::BOB, "bob-tss-server:3002".to_string(), + provisioning_certification_key::BOB.clone(), ); vec![alice, bob] @@ -207,7 +210,8 @@ pub fn testnet_local_initial_tss_servers() -> Vec<(TssAccountId, TssX25519Public /// /// Note that if the KVDB of the TSS is deleted at any point during this process you will end up /// with different `AccountID`s and `PublicKey`s. -pub fn testnet_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, TssEndpoint)> { +pub fn testnet_initial_tss_servers( +) -> Vec<(TssAccountId, TssX25519PublicKey, TssEndpoint, BoundedVecEncodedVerifyingKey)> { use std::str::FromStr; let node_1a = ( @@ -218,6 +222,7 @@ pub fn testnet_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, T 198, 84, 61, 178, 36, 191, 56, 41, 39, 173, 70, 9, 67, ], "100.26.207.49:3001".to_string(), + provisioning_certification_key::ALICE.clone(), ); let node_1b = ( @@ -228,6 +233,7 @@ pub fn testnet_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, T 10, 107, 31, 67, 10, 98, 215, 34, 26, 10, 188, 59, 71, 100, ], "34.200.237.166:3001".to_string(), + provisioning_certification_key::BOB.clone(), ); let node_1c = ( @@ -238,6 +244,7 @@ pub fn testnet_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, T 36, 157, 25, 170, 72, 247, 152, 130, 139, 244, 4, 67, 162, 0, ], "184.72.189.154:3001".to_string(), + provisioning_certification_key::CHARLIE.clone(), ); let node_2a = ( @@ -248,6 +255,7 @@ pub fn testnet_initial_tss_servers() -> Vec<(TssAccountId, TssX25519PublicKey, T 196, 3, 154, 37, 23, 133, 28, 168, 221, 37, 204, 186, 61, ], "184.73.19.95:3001".to_string(), + provisioning_certification_key::DAVE.clone(), ); vec![node_1a, node_1b, node_1c, node_2a] @@ -293,7 +301,12 @@ pub fn testnet_genesis_config( )>, initial_nominators: Vec, root_key: AccountId, - initial_tss_servers: Vec<(TssAccountId, TssX25519PublicKey, TssEndpoint)>, + initial_tss_servers: Vec<( + TssAccountId, + TssX25519PublicKey, + TssEndpoint, + BoundedVecEncodedVerifyingKey, + )>, ) -> serde_json::Value { assert!( initial_authorities.len() == initial_tss_servers.len(), @@ -410,7 +423,7 @@ pub fn testnet_genesis_config( .iter() .zip(initial_tss_servers.iter()) .map(|(auth, tss)| { - (auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec())) + (auth.0.clone(), (tss.0.clone(), tss.1, tss.2.as_bytes().to_vec(), tss.3.clone())) }) .collect::>(), proactive_refresh_data: (vec![], vec![]), diff --git a/pallets/attestation/Cargo.toml b/pallets/attestation/Cargo.toml index 44d63ae1c..ded3b1a93 100644 --- a/pallets/attestation/Cargo.toml +++ b/pallets/attestation/Cargo.toml @@ -27,7 +27,7 @@ entropy-shared={ version="0.2.0", path="../../crates/shared", features=[ "wasm-no-std", ], default-features=false } pallet-staking-extension={ version="0.2.0", path="../staking", default-features=false } -tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff" } +tdx-quote={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2" } [dev-dependencies] pallet-session ={ version="29.0.0", default-features=false } @@ -38,7 +38,7 @@ pallet-timestamp ={ version="28.0.0", default-features=false } sp-npos-elections ={ version="27.0.0", default-features=false } frame-election-provider-support={ version="29.0.0", default-features=false } pallet-staking-reward-curve ={ version="11.0.0" } -tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="f7968ff", features=["mock"] } +tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote", rev="cb167f2", features=["mock"] } rand_core ="0.6.4" [features] diff --git a/pallets/attestation/src/benchmarking.rs b/pallets/attestation/src/benchmarking.rs index f3c88604f..16b4de2ad 100644 --- a/pallets/attestation/src/benchmarking.rs +++ b/pallets/attestation/src/benchmarking.rs @@ -15,6 +15,7 @@ use entropy_shared::QuoteInputData; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_support::BoundedVec; use frame_system::{EventRecord, RawOrigin}; use pallet_staking_extension::{ServerInfo, ThresholdServers, ThresholdToStash}; @@ -22,12 +23,19 @@ use super::*; #[allow(unused)] use crate::Pallet as AttestationPallet; -// This is a randomly generated secret p256 ECDSA key -const ENCLAVE_SIGNING_KEY: [u8; 32] = [ +/// This is a randomly generated secret p256 ECDSA key - for mocking attestation +const ATTESTATION_KEY: [u8; 32] = [ 167, 184, 203, 130, 240, 249, 191, 129, 206, 9, 200, 29, 99, 197, 64, 81, 135, 166, 59, 73, 31, 27, 206, 207, 69, 248, 56, 195, 64, 92, 109, 46, ]; +/// This is a randomly generated secret p256 ECDSA key - for mocking the provisioning certification +/// key +const PCK: [u8; 32] = [ + 117, 153, 212, 7, 220, 16, 181, 32, 110, 138, 4, 68, 208, 37, 104, 54, 1, 110, 232, 207, 100, + 168, 16, 99, 66, 83, 21, 178, 81, 155, 132, 37, +]; + fn assert_last_event(generic_event: ::RuntimeEvent) { let events = frame_system::Pallet::::events(); let system_event: ::RuntimeEvent = generic_event.into(); @@ -41,7 +49,9 @@ benchmarks! { let attestee: T::AccountId = whitelisted_caller(); let nonce = [0; 32]; - let signing_key = tdx_quote::SigningKey::from_bytes(&ENCLAVE_SIGNING_KEY.into()).unwrap(); + let attestation_key = tdx_quote::SigningKey::from_bytes(&ATTESTATION_KEY.into()).unwrap(); + let pck = tdx_quote::SigningKey::from_bytes(&PCK.into()).unwrap(); + let pck_encoded = tdx_quote::encode_verifying_key(pck.verifying_key()).unwrap(); let input_data = QuoteInputData::new( &attestee, // TSS Account ID @@ -49,7 +59,7 @@ benchmarks! { nonce, 1, // Block number ); - let quote = tdx_quote::Quote::mock(signing_key.clone(), input_data.0).as_bytes().to_vec(); + let quote = tdx_quote::Quote::mock(attestation_key.clone(), pck, input_data.0).as_bytes().to_vec(); // Insert a pending attestation so that this quote is expected >::insert(attestee.clone(), nonce); @@ -63,6 +73,7 @@ benchmarks! { tss_account: attestee.clone(), x25519_public_key: [0; 32], endpoint: b"http://localhost:3001".to_vec(), + provisioning_certification_key: pck_encoded.to_vec().try_into().unwrap(), }); }: _(RawOrigin::Signed(attestee.clone()), quote.clone()) diff --git a/pallets/attestation/src/lib.rs b/pallets/attestation/src/lib.rs index ebab0a19e..ae09ea549 100644 --- a/pallets/attestation/src/lib.rs +++ b/pallets/attestation/src/lib.rs @@ -51,7 +51,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_std::vec::Vec; - use tdx_quote::Quote; + use tdx_quote::{decode_verifying_key, Quote}; pub use crate::weights::WeightInfo; @@ -123,6 +123,10 @@ pub mod pallet { NoServerInfo, /// Unacceptable VM image running BadMrtdValue, + /// Cannot decode verifying key (PCK) + CannotDecodeVerifyingKey, + /// Could not verify PCK signature + PckVerification, } #[pallet::call] @@ -142,17 +146,15 @@ pub mod pallet { let nonce = PendingAttestations::::get(&who).ok_or(Error::::UnexpectedAttestation)?; - // Parse the quote (which internally verifies the signature) + // Parse the quote (which internally verifies the attestation key signature) let quote = Quote::from_bytes("e).map_err(|_| Error::::BadQuote)?; - // Get associated x25519 public key from staking pallet - let x25519_public_key = { + // Get associated server info from staking pallet + let server_info = { let stash_account = pallet_staking_extension::Pallet::::threshold_to_stash(&who) .ok_or(Error::::NoStashAccount)?; - let server_info = - pallet_staking_extension::Pallet::::threshold_server(&stash_account) - .ok_or(Error::::NoServerInfo)?; - server_info.x25519_public_key + pallet_staking_extension::Pallet::::threshold_server(&stash_account) + .ok_or(Error::::NoServerInfo)? }; // Get current block number @@ -163,7 +165,7 @@ pub mod pallet { // Check report input data matches the nonce, TSS details and block number let expected_input_data = - QuoteInputData::new(&who, x25519_public_key, nonce, block_number); + QuoteInputData::new(&who, server_info.x25519_public_key, nonce, block_number); ensure!( quote.report_input_data() == expected_input_data.0, Error::::IncorrectInputData @@ -175,8 +177,18 @@ pub mod pallet { let accepted_mrtd_values = pallet_parameters::Pallet::::accepted_mrtd_values(); ensure!(accepted_mrtd_values.contains(&mrtd_value), Error::::BadMrtdValue); - // TODO #982 Check that the attestation public key matches that from PCK certificate - let _attestation_key = quote.attestation_key; + // Check that the attestation public key is signed with the PCK + let provisioning_certification_key = decode_verifying_key( + &server_info + .provisioning_certification_key + .to_vec() + .try_into() + .map_err(|_| Error::::CannotDecodeVerifyingKey)?, + ) + .map_err(|_| Error::::CannotDecodeVerifyingKey)?; + quote + .verify_with_pck(provisioning_certification_key) + .map_err(|_| Error::::PckVerification)?; // Remove the entry from PendingAttestations PendingAttestations::::remove(&who); diff --git a/pallets/attestation/src/mock.rs b/pallets/attestation/src/mock.rs index 086153d1f..3513578c4 100644 --- a/pallets/attestation/src/mock.rs +++ b/pallets/attestation/src/mock.rs @@ -36,6 +36,13 @@ use std::cell::RefCell; use crate as pallet_attestation; +/// This is a randomly generated secret p256 ECDSA key - for mocking the provisioning certification +/// key +pub const PCK: [u8; 32] = [ + 117, 153, 212, 7, 220, 16, 181, 32, 110, 138, 4, 68, 208, 37, 104, 54, 1, 110, 232, 207, 100, + 168, 16, 99, 66, 83, 21, 178, 81, 155, 132, 37, +]; + const NULL_ARR: [u8; 32] = [0; 32]; type Block = frame_system::mocking::MockBlock; @@ -342,10 +349,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { }; pallet_attestation.assimilate_storage(&mut t).unwrap(); + let pck = tdx_quote::SigningKey::from_bytes(&PCK.into()).unwrap(); + let pck_encoded = tdx_quote::encode_verifying_key(&pck.verifying_key()).unwrap(); let pallet_staking_extension = pallet_staking_extension::GenesisConfig:: { threshold_servers: vec![ - // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL)) - (5, (0, NULL_ARR, vec![20])), + // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL, PCK)) + (5, (0, NULL_ARR, vec![20], pck_encoded.to_vec().try_into().unwrap())), ], proactive_refresh_data: (vec![], vec![]), mock_signer_rotate: (false, vec![], vec![]), diff --git a/pallets/attestation/src/tests.rs b/pallets/attestation/src/tests.rs index 7e34966e2..31ef6c53e 100644 --- a/pallets/attestation/src/tests.rs +++ b/pallets/attestation/src/tests.rs @@ -27,9 +27,8 @@ fn attest() { let nonce = Attestation::pending_attestations(ATTESTEE).unwrap(); assert_eq!(nonce, [0; 32]); - // For now it doesn't matter what this is, but once we handle PCK certificates this will - // need to correspond to the public key in the certificate - let signing_key = tdx_quote::SigningKey::random(&mut OsRng); + let attestation_key = tdx_quote::SigningKey::random(&mut OsRng); + let pck = tdx_quote::SigningKey::from_bytes(&PCK.into()).unwrap(); let input_data = QuoteInputData::new( ATTESTEE, // TSS Account ID @@ -37,7 +36,7 @@ fn attest() { nonce, 0, // Block number ); - let quote = tdx_quote::Quote::mock(signing_key.clone(), input_data.0); + let quote = tdx_quote::Quote::mock(attestation_key.clone(), pck, input_data.0); assert_ok!( Attestation::attest(RuntimeOrigin::signed(ATTESTEE), quote.as_bytes().to_vec(),) ); diff --git a/pallets/propagation/src/mock.rs b/pallets/propagation/src/mock.rs index a87be8a69..2d99b152d 100644 --- a/pallets/propagation/src/mock.rs +++ b/pallets/propagation/src/mock.rs @@ -28,7 +28,7 @@ use sp_runtime::{ curve::PiecewiseLinear, testing::{TestXt, UintAuthorityId}, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - BuildStorage, Perbill, + BoundedVec, BuildStorage, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; use std::cell::RefCell; @@ -379,11 +379,11 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let pallet_staking_extension = pallet_staking_extension::GenesisConfig:: { threshold_servers: vec![ - // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL)) - (5, (7, NULL_ARR, vec![20])), - (6, (8, NULL_ARR, vec![40])), - (1, (3, NULL_ARR, vec![10])), - (2, (4, NULL_ARR, vec![11])), + // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL, PCK)) + (5, (7, NULL_ARR, vec![20], BoundedVec::with_max_capacity())), + (6, (8, NULL_ARR, vec![40], BoundedVec::with_max_capacity())), + (1, (3, NULL_ARR, vec![10], BoundedVec::with_max_capacity())), + (2, (4, NULL_ARR, vec![11], BoundedVec::with_max_capacity())), ], proactive_refresh_data: (vec![], vec![]), mock_signer_rotate: (false, vec![], vec![]), diff --git a/pallets/registry/src/benchmarking.rs b/pallets/registry/src/benchmarking.rs index 92021f801..79e2c7710 100644 --- a/pallets/registry/src/benchmarking.rs +++ b/pallets/registry/src/benchmarking.rs @@ -52,8 +52,12 @@ pub fn add_non_syncing_validators( ) -> Vec<::ValidatorId> { let validators = create_validators::(validator_amount, SEED); let account = account::("ts_account", 1, SEED); - let server_info = - ServerInfo { tss_account: account, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: account, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; for (c, validator) in validators.iter().enumerate() { >::insert(validator, server_info.clone()); if c >= syncing_validators.try_into().unwrap() { diff --git a/pallets/registry/src/mock.rs b/pallets/registry/src/mock.rs index 3d2c10f19..3101f1760 100644 --- a/pallets/registry/src/mock.rs +++ b/pallets/registry/src/mock.rs @@ -366,12 +366,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let pallet_staking_extension = pallet_staking_extension::GenesisConfig:: { threshold_servers: vec![ - // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL)) - (5, (7, NULL_ARR, vec![20])), - (6, (8, NULL_ARR, vec![40])), - (1, (3, NULL_ARR, vec![10])), - (2, (4, NULL_ARR, vec![11])), - (7, (4, NULL_ARR, vec![50])), + // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL, PCK)) + (5, (7, NULL_ARR, vec![20], BoundedVec::with_max_capacity())), + (6, (8, NULL_ARR, vec![40], BoundedVec::with_max_capacity())), + (1, (3, NULL_ARR, vec![10], BoundedVec::with_max_capacity())), + (2, (4, NULL_ARR, vec![11], BoundedVec::with_max_capacity())), + (7, (4, NULL_ARR, vec![50], BoundedVec::with_max_capacity())), ], proactive_refresh_data: (vec![], vec![]), mock_signer_rotate: (false, vec![], vec![]), diff --git a/pallets/registry/src/tests.rs b/pallets/registry/src/tests.rs index ccde65810..f382bd34c 100644 --- a/pallets/registry/src/tests.rs +++ b/pallets/registry/src/tests.rs @@ -57,12 +57,24 @@ fn setup_programs( fn it_tests_get_validators_info() { new_test_ext().execute_with(|| { let result_1 = Registry::get_validators_info().unwrap(); - let server_info_1 = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![10] }; - let server_info_2 = - ServerInfo { tss_account: 4, x25519_public_key: NULL_ARR, endpoint: vec![11] }; - let server_info_3 = - ServerInfo { tss_account: 7, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info_1 = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![10], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; + let server_info_2 = ServerInfo { + tss_account: 4, + x25519_public_key: NULL_ARR, + endpoint: vec![11], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; + let server_info_3 = ServerInfo { + tss_account: 7, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_eq!(result_1, vec![server_info_1, server_info_2, server_info_3]); }); diff --git a/pallets/staking/src/benchmarking.rs b/pallets/staking/src/benchmarking.rs index 5fce1157b..088342a9a 100644 --- a/pallets/staking/src/benchmarking.rs +++ b/pallets/staking/src/benchmarking.rs @@ -21,6 +21,7 @@ use frame_support::{ assert_ok, ensure, sp_runtime::traits::StaticLookup, traits::{Currency, Get}, + BoundedVec, }; use frame_system::{EventRecord, RawOrigin}; use pallet_parameters::{SignersInfo, SignersSize}; @@ -77,8 +78,12 @@ fn prep_bond_and_validate( reward_destination, )); - let server_info = - ServerInfo { tss_account: threshold, x25519_public_key, endpoint: vec![20, 20] }; + let server_info = ServerInfo { + tss_account: threshold, + x25519_public_key, + endpoint: vec![20, 20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; if validate_also { assert_ok!(>::validate( @@ -120,6 +125,7 @@ benchmarks! { endpoint: vec![20, 20], tss_account: _bonder.clone(), x25519_public_key: NULL_ARR, + provisioning_certification_key: BoundedVec::with_max_capacity(), }; assert_last_event::(Event::::ThresholdAccountChanged(bonder, server_info).into()); } @@ -161,6 +167,7 @@ benchmarks! { tss_account: threshold.clone(), x25519_public_key: NULL_ARR, endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), }; }: _(RawOrigin::Signed(bonder.clone()), validator_preference, server_info) diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index f6ea6f16a..85b51ae5a 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -115,6 +115,7 @@ pub mod pallet { pub tss_account: AccountId, pub x25519_public_key: X25519PublicKey, pub endpoint: TssServerURL, + pub provisioning_certification_key: VerifyingKey, } /// Info that is requiered to do a proactive refresh #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, Default)] @@ -238,7 +239,7 @@ pub mod pallet { /// A type used to simplify the genesis configuration definition. pub type ThresholdServersConfig = ( ::ValidatorId, - (::AccountId, X25519PublicKey, TssServerURL), + (::AccountId, X25519PublicKey, TssServerURL, VerifyingKey), ); #[pallet::genesis_config] @@ -265,6 +266,7 @@ pub mod pallet { tss_account: server_info_tuple.0.clone(), x25519_public_key: server_info_tuple.1, endpoint: server_info_tuple.2.clone(), + provisioning_certification_key: server_info_tuple.3.clone(), }; ThresholdServers::::insert(validator_stash, server_info.clone()); diff --git a/pallets/staking/src/mock.rs b/pallets/staking/src/mock.rs index 0d1fe7159..9ab987bfd 100644 --- a/pallets/staking/src/mock.rs +++ b/pallets/staking/src/mock.rs @@ -400,8 +400,11 @@ pub fn new_test_ext() -> sp_io::TestExternalities { balances: vec![(1, 100), (2, 100), (3, 100), (4, 100)], }; let pallet_staking_extension = pallet_staking_extension::GenesisConfig:: { - // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL)) - threshold_servers: vec![(5, (7, NULL_ARR, vec![20])), (6, (8, NULL_ARR, vec![40]))], + // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL, VerifyingKey)) + threshold_servers: vec![ + (5, (7, NULL_ARR, vec![20], BoundedVec::with_max_capacity())), + (6, (8, NULL_ARR, vec![40], BoundedVec::with_max_capacity())), + ], proactive_refresh_data: (vec![], vec![]), mock_signer_rotate: (false, vec![], vec![]), }; diff --git a/pallets/staking/src/tests.rs b/pallets/staking/src/tests.rs index a6639b9f5..7f1c21ba1 100644 --- a/pallets/staking/src/tests.rs +++ b/pallets/staking/src/tests.rs @@ -22,6 +22,7 @@ use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Phase}; use pallet_parameters::SignersSize; use pallet_session::SessionManager; +use sp_runtime::BoundedVec; const NULL_ARR: [u8; 32] = [0; 32]; #[test] @@ -29,11 +30,21 @@ fn basic_setup_works() { new_test_ext().execute_with(|| { assert_eq!( Staking::threshold_server(5).unwrap(), - ServerInfo { tss_account: 7, x25519_public_key: NULL_ARR, endpoint: vec![20] } + ServerInfo { + tss_account: 7, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity() + } ); assert_eq!( Staking::threshold_server(6).unwrap(), - ServerInfo { tss_account: 8, x25519_public_key: NULL_ARR, endpoint: vec![40] } + ServerInfo { + tss_account: 8, + x25519_public_key: NULL_ARR, + endpoint: vec![40], + provisioning_certification_key: BoundedVec::with_max_capacity() + } ); assert_eq!(Staking::threshold_to_stash(7).unwrap(), 5); assert_eq!(Staking::threshold_to_stash(8).unwrap(), 6); @@ -51,8 +62,12 @@ fn it_takes_in_an_endpoint() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(1), pallet_staking::ValidatorPrefs::default(), @@ -68,6 +83,7 @@ fn it_takes_in_an_endpoint() { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20, 20, 20, 20], + provisioning_certification_key: BoundedVec::with_max_capacity(), }; assert_noop!( Staking::validate( @@ -78,8 +94,12 @@ fn it_takes_in_an_endpoint() { Error::::EndpointTooLong ); - let server_info = - ServerInfo { tss_account: 5, x25519_public_key: NULL_ARR, endpoint: vec![20, 20] }; + let server_info = ServerInfo { + tss_account: 5, + x25519_public_key: NULL_ARR, + endpoint: vec![20, 20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_noop!( Staking::validate( RuntimeOrigin::signed(4), @@ -100,8 +120,12 @@ fn it_will_not_allow_validator_to_use_existing_tss_account() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(1), pallet_staking::ValidatorPrefs::default(), @@ -134,8 +158,12 @@ fn it_changes_endpoint() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(1), pallet_staking::ValidatorPrefs::default(), @@ -161,8 +189,12 @@ fn it_changes_threshold_account() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(1), pallet_staking::ValidatorPrefs::default(), @@ -185,8 +217,12 @@ fn it_changes_threshold_account() { pallet_staking::RewardDestination::Account(2), )); - let server_info = - ServerInfo { tss_account: 5, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 5, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(2), pallet_staking::ValidatorPrefs::default(), @@ -209,8 +245,12 @@ fn it_will_not_allow_existing_tss_account_when_changing_threshold_account() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(1), pallet_staking::ValidatorPrefs::default(), @@ -224,8 +264,12 @@ fn it_will_not_allow_existing_tss_account_when_changing_threshold_account() { pallet_staking::RewardDestination::Account(2), )); - let server_info = - ServerInfo { tss_account: 5, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 5, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(2), pallet_staking::ValidatorPrefs::default(), @@ -250,8 +294,12 @@ fn it_deletes_when_no_bond_left() { pallet_staking::RewardDestination::Account(1), )); - let server_info = - ServerInfo { tss_account: 3, x25519_public_key: NULL_ARR, endpoint: vec![20] }; + let server_info = ServerInfo { + tss_account: 3, + x25519_public_key: NULL_ARR, + endpoint: vec![20], + provisioning_certification_key: BoundedVec::with_max_capacity(), + }; assert_ok!(Staking::validate( RuntimeOrigin::signed(2), pallet_staking::ValidatorPrefs::default(),