Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow rotating a subset of collators instead of all of them #770

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a22e866
Allow rotating a subset of collators instead of all of them
tmpolaczyk Nov 28, 2024
f65e0df
Add tests
tmpolaczyk Nov 28, 2024
2cc7df4
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Nov 28, 2024
f77e0c4
Refactor tests
tmpolaczyk Nov 28, 2024
759ce4f
Typo
tmpolaczyk Nov 28, 2024
aaadfcf
typescript-api
tmpolaczyk Nov 28, 2024
1bebbc1
Fix config migration for dancelight
tmpolaczyk Nov 29, 2024
3d04b36
Docs and fmt
tmpolaczyk Nov 29, 2024
7720c6c
Fix import
tmpolaczyk Nov 29, 2024
14bc0b3
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 2, 2024
7eb719f
PR comments
tmpolaczyk Dec 2, 2024
767b47b
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 2, 2024
d6df2fd
typescript-api
tmpolaczyk Dec 2, 2024
1eb3fb6
Add pre migration test
tmpolaczyk Dec 5, 2024
973d915
Merge remote-tracking branch 'origin/master' into HEAD
tmpolaczyk Dec 5, 2024
d0ef62f
fmt
tmpolaczyk Dec 5, 2024
e1f9892
Add post migration test
tmpolaczyk Dec 9, 2024
faac9e9
Document past migration runtime version
tmpolaczyk Dec 9, 2024
b6f46d7
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 9, 2024
da987b7
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 11, 2024
57413f5
WIP not ready
tmpolaczyk Dec 12, 2024
7026106
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 13, 2024
2feaa31
WIP tests, no randomness
tmpolaczyk Dec 13, 2024
6dff48a
add possibility of injecting randomness
girazoki Dec 18, 2024
b64e338
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 18, 2024
099b65d
Add new com
girazoki Dec 18, 2024
dda5a29
WIP tests
tmpolaczyk Dec 18, 2024
e28a579
Add parathread tests, not rotating for some reason
tmpolaczyk Dec 18, 2024
e01da83
WIP register another parthread, still broken
tmpolaczyk Dec 19, 2024
d3c2405
Add seed to manual randomness, fixing test
tmpolaczyk Dec 20, 2024
5e35794
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 20, 2024
9cb9158
Merge remote-tracking branch 'origin/master' into tomasz-rotate-subset
tmpolaczyk Dec 20, 2024
f51beab
fmt
tmpolaczyk Dec 20, 2024
75d6a45
whitespace
tmpolaczyk Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ flashbox-runtime = { path = "runtime/flashbox", default-features = false }
dancelight-runtime = { path = "solo-chains/runtime/dancelight", default-features = false }
dancelight-runtime-constants = { path = "solo-chains/runtime/dancelight/constants", default-features = false }
ethabi = { package = "ethabi-decode", version = "1.0.0", default-features = false }
manual-randomness-rpc = { path = "client/manual-randomness" }
manual-xcm-rpc = { path = "client/manual-xcm" }
node-common = { path = "client/node-common" }
services-payment-rpc = { path = "client/services-payment" }
Expand Down
19 changes: 19 additions & 0 deletions client/manual-randomness/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "manual-randomness-rpc"
authors = { workspace = true }
edition = "2021"
license = "GPL-3.0-only"
repository = { workspace = true }
version = "0.1.0"

[lints]
workspace = true

[dependencies]
cumulus-primitives-core = { workspace = true, features = [ "std" ] }
flume = { workspace = true }
hex-literal = { workspace = true }
jsonrpsee = { workspace = true, features = [ "macros", "server" ] }
parity-scale-codec = { workspace = true, features = [ "std" ] }
sp-core = { workspace = true, features = [ "std" ] }
staging-xcm = { workspace = true }
70 changes: 70 additions & 0 deletions client/manual-randomness/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (C) Moondance Labs Ltd.
// This file is part of Tanssi.

// Tanssi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Tanssi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Tanssi. If not, see <http://www.gnu.org/licenses/>.
use sp_core::H256;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};

#[rpc(server)]
#[jsonrpsee::core::async_trait]
pub trait ManualRandomnessApi {
/// Inject randomness
#[method(name = "mock_activateRandomness")]
async fn activate_randomness(&self, seed: Option<H256>) -> RpcResult<()>;
#[method(name = "mock_deactivateRandomness")]
async fn deactivate_randomness(&self) -> RpcResult<()>;
}

pub struct ManualRandomness {
pub randomness_message_channel: flume::Sender<(bool, Option<[u8; 32]>)>,
}

#[jsonrpsee::core::async_trait]
impl ManualRandomnessApiServer for ManualRandomness {
async fn activate_randomness(&self, seed: Option<H256>) -> RpcResult<()> {
let randomness_message_channel = self.randomness_message_channel.clone();

// Push the message to the shared channel where it will be queued up
// to be injected in to an upcoming block.
randomness_message_channel
.send_async((true, seed.map(|x| x.into())))
.await
.map_err(|err| internal_err(err.to_string()))?;

Ok(())
}

async fn deactivate_randomness(&self) -> RpcResult<()> {
let randomness_message_channel = self.randomness_message_channel.clone();

// Push the message to the shared channel where it will be queued up
// to be injected in to an upcoming block.
randomness_message_channel
.send_async((false, None))
.await
.map_err(|err| internal_err(err.to_string()))?;

Ok(())
}
}

// This bit cribbed from frontier.
pub fn internal_err<T: AsRef<str>>(message: T) -> jsonrpsee::types::ErrorObjectOwned {
jsonrpsee::types::error::ErrorObject::borrowed(
jsonrpsee::types::error::INTERNAL_ERROR_CODE,
message.as_ref(),
None,
)
.into_owned()
}
1 change: 1 addition & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dancebox-runtime = { workspace = true, features = [ "std" ] }
dp-container-chain-genesis-data = { workspace = true, features = [ "json", "std" ] }
dp-slot-duration-runtime-api = { workspace = true }
flashbox-runtime = { workspace = true, features = [ "std" ] }
manual-randomness-rpc = { workspace = true }
manual-xcm-rpc = { workspace = true }
node-common = { workspace = true }
pallet-author-noting-runtime-api = { workspace = true, features = [ "std" ] }
Expand Down
2 changes: 2 additions & 0 deletions node/src/chain_spec/dancebox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub fn development_config(
parathreads_per_collator: 1,
target_container_chain_fullness: Perbill::from_percent(80),
max_parachain_cores_percentage: None,
full_rotation_mode: Default::default(),
},
..Default::default()
},
Expand Down Expand Up @@ -161,6 +162,7 @@ pub fn local_dancebox_config(
parathreads_per_collator: 1,
target_container_chain_fullness: Perbill::from_percent(80),
max_parachain_cores_percentage: None,
full_rotation_mode: Default::default(),
},
..Default::default()
},
Expand Down
2 changes: 2 additions & 0 deletions node/src/chain_spec/flashbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub fn development_config(
parathreads_per_collator: 1,
target_container_chain_fullness: Perbill::from_percent(80),
max_parachain_cores_percentage: None,
full_rotation_mode: Default::default(),
},
..Default::default()
},
Expand Down Expand Up @@ -161,6 +162,7 @@ pub fn local_flashbox_config(
parathreads_per_collator: 1,
target_container_chain_fullness: Perbill::from_percent(80),
max_parachain_cores_percentage: None,
full_rotation_mode: Default::default(),
},
..Default::default()
},
Expand Down
13 changes: 13 additions & 0 deletions node/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use {
cumulus_primitives_core::ParaId,
dancebox_runtime::{opaque::Block, AccountId, Index as Nonce},
manual_randomness_rpc::{ManualRandomness, ManualRandomnessApiServer},
manual_xcm_rpc::{ManualXcm, ManualXcmApiServer},
polkadot_primitives::Hash,
sc_client_api::{AuxStore, UsageProvider},
Expand Down Expand Up @@ -55,6 +56,8 @@ pub struct FullDeps<C, P> {
pub command_sink: Option<futures::channel::mpsc::Sender<EngineCommand<Hash>>>,
/// Channels for manual xcm messages (downward, hrmp)
pub xcm_senders: Option<(flume::Sender<Vec<u8>>, flume::Sender<(ParaId, Vec<u8>)>)>,
/// Channels for manually activating the randomness
pub randomness_sender: Option<flume::Sender<(bool, Option<[u8; 32]>)>>,
}

/// Instantiate all RPC extensions.
Expand Down Expand Up @@ -84,6 +87,7 @@ where
pool,
command_sink,
xcm_senders,
randomness_sender,
} = deps;

module.merge(System::new(client.clone(), pool).into_rpc())?;
Expand All @@ -108,5 +112,14 @@ where
)?;
}

if let Some(randomness_message_channel) = randomness_sender {
module.merge(
ManualRandomness {
randomness_message_channel,
}
.into_rpc(),
)?;
}

Ok(module)
}
53 changes: 52 additions & 1 deletion node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use {
pallet_author_noting_runtime_api::AuthorNotingApi,
pallet_data_preservers_runtime_api::DataPreserversApi,
pallet_registrar_runtime_api::RegistrarApi,
parity_scale_codec::Encode,
parity_scale_codec::{Decode, Encode},
polkadot_cli::ProvideRuntimeApi,
polkadot_parachain_primitives::primitives::HeadData,
polkadot_service::Handle,
Expand Down Expand Up @@ -94,6 +94,9 @@ use {

mod mocked_relay_keys;

// We use this to detect whether randomness is activated
const RANDOMNESS_ACTIVATED_AUX_KEY: &[u8] = b"__DEV_RANDOMNESS_ACTIVATED";

type FullBackend = TFullBackend<Block>;

pub struct NodeConfig;
Expand Down Expand Up @@ -287,6 +290,7 @@ async fn start_node_impl(
pool: transaction_pool.clone(),
command_sink: None,
xcm_senders: None,
randomness_sender: None,
};

crate::rpc::create_full(deps).map_err(Into::into)
Expand Down Expand Up @@ -893,11 +897,17 @@ pub fn start_dev_node(
// production.
let mut command_sink = None;
let mut xcm_senders = None;
let mut randomness_sender = None;
if parachain_config.role.is_authority() {
let client = node_builder.client.clone();
let (downward_xcm_sender, downward_xcm_receiver) = flume::bounded::<Vec<u8>>(100);

let (hrmp_xcm_sender, hrmp_xcm_receiver) = flume::bounded::<(ParaId, Vec<u8>)>(100);
// Create channels for mocked parachain candidates.
let (mock_randomness_sender, mock_randomness_receiver) = flume::bounded::<(bool, Option<[u8; 32]>)>(100);

xcm_senders = Some((downward_xcm_sender, hrmp_xcm_sender));
randomness_sender = Some(mock_randomness_sender);

command_sink = node_builder.install_manual_seal(ManualSealConfiguration {
block_import,
Expand Down Expand Up @@ -958,6 +968,34 @@ pub fn start_dev_node(
let downward_xcm_receiver = downward_xcm_receiver.clone();
let hrmp_xcm_receiver = hrmp_xcm_receiver.clone();

let randomness_enabler_messages: Vec<(bool, Option<[u8; 32]>)> = mock_randomness_receiver.drain().collect();

// If there is a value to be updated, we update it
if let Some((enable_randomness, new_seed)) = randomness_enabler_messages.last() {
let value = client
.get_aux(RANDOMNESS_ACTIVATED_AUX_KEY)
.expect("Should be able to query aux storage; qed").unwrap_or((false, Option::<[u8; 32]>::None).encode());
let (_mock_additional_randomness, mut mock_randomness_seed): (bool, Option<[u8; 32]>) = Decode::decode(&mut value.as_slice()).expect("Boolean non-decodable");

if let Some(new_seed) = new_seed {
mock_randomness_seed = Some(*new_seed);
}

client
.insert_aux(
&[(RANDOMNESS_ACTIVATED_AUX_KEY, (enable_randomness, mock_randomness_seed).encode().as_slice())],
&[],
)
.expect("Should be able to write to aux storage; qed");
}

// We read the value
// If error when reading, we simply put false
let value = client
.get_aux(RANDOMNESS_ACTIVATED_AUX_KEY)
.expect("Should be able to query aux storage; qed").unwrap_or((false, Option::<[u8; 32]>::None).encode());
let (mock_additional_randomness, mock_randomness_seed): (bool, Option<[u8; 32]>) = Decode::decode(&mut value.as_slice()).expect("Boolean non-decodable");

let client_for_xcm = client.clone();
async move {
let mocked_author_noting =
Expand All @@ -974,6 +1012,18 @@ pub fn start_dev_node(
let (registrar_paras_key_2002, para_info_2002) = mocked_relay_keys::get_mocked_registrar_paras(2002.into());
additional_keys.extend([(para_head_key, para_head_data), (relay_slot_key, Slot::from(relay_slot).encode()), (registrar_paras_key_2002, para_info_2002)]);

if mock_additional_randomness {
let mut mock_randomness: [u8; 32] = [0u8; 32];
mock_randomness[..4].copy_from_slice(&current_para_block.to_be_bytes());
if let Some(seed) = mock_randomness_seed {
for i in 0..32 {
mock_randomness[i] ^= seed[i];
}
}
additional_keys.extend([(RelayWellKnownKeys::CURRENT_BLOCK_RANDOMNESS.to_vec(), Some(mock_randomness).encode())]);
log::info!("mokcing randomnessss!!! {}", current_para_block);
}

let time = MockTimestampInherentDataProvider;
let mocked_parachain = MockValidationDataInherentDataProvider {
current_para_block,
Expand Down Expand Up @@ -1011,6 +1061,7 @@ pub fn start_dev_node(
pool: transaction_pool.clone(),
command_sink: command_sink.clone(),
xcm_senders: xcm_senders.clone(),
randomness_sender: randomness_sender.clone(),
};

crate::rpc::create_full(deps).map_err(Into::into)
Expand Down
Loading
Loading