Rococo & Westend People Chain (#2281)

Rococo and Westend runtimes for the "People Chain". This chain contains
the Identity pallet with plans to migrate all related data from the
Relay Chain.

Changes `IdentityInfo` to:

- Remove `additional_fields`.
- Add `github` and `discord` as first class fields. From scraping chain
data, these were the only two additional fields used (for the Fellowship
and Ambassador Program, respectively).
- Rename `riot` to `matrix`.

Note: This will use the script in
https://github.com/paritytech/polkadot-sdk/pull/2025 to generate the
genesis state.

TODO:

- [x] https://github.com/paritytech/polkadot-sdk/pull/1814 and
integration of the Identity Migrator pallet for migration.
- [x] Tests: https://github.com/paritytech/polkadot-sdk/pull/2373

---------

Co-authored-by: Muharem <ismailov.m.h@gmail.com>
Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
Co-authored-by: Dónal Murray <donal.murray@parity.io>
Co-authored-by: Richard Melkonian <35300528+0xmovses@users.noreply.github.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
joe petrowski
2023-12-22 21:28:09 +01:00
committed by GitHub
parent 4c0e0e0713
commit ecbbb5a736
111 changed files with 12730 additions and 258 deletions
+6
View File
@@ -38,6 +38,8 @@ coretime-rococo-runtime = { path = "../parachains/runtimes/coretime/coretime-roc
coretime-westend-runtime = { path = "../parachains/runtimes/coretime/coretime-westend" }
bridge-hub-westend-runtime = { path = "../parachains/runtimes/bridge-hubs/bridge-hub-westend" }
penpal-runtime = { path = "../parachains/runtimes/testing/penpal" }
people-rococo-runtime = { path = "../parachains/runtimes/people/people-rococo" }
people-westend-runtime = { path = "../parachains/runtimes/people/people-westend" }
jsonrpsee = { version = "0.16.2", features = ["server"] }
parachains-common = { path = "../parachains/common" }
@@ -135,6 +137,8 @@ runtime-benchmarks = [
"glutton-westend-runtime/runtime-benchmarks",
"parachains-common/runtime-benchmarks",
"penpal-runtime/runtime-benchmarks",
"people-rococo-runtime/runtime-benchmarks",
"people-westend-runtime/runtime-benchmarks",
"polkadot-cli/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-service/runtime-benchmarks",
@@ -156,6 +160,8 @@ try-runtime = [
"glutton-westend-runtime/try-runtime",
"pallet-transaction-payment/try-runtime",
"penpal-runtime/try-runtime",
"people-rococo-runtime/try-runtime",
"people-westend-runtime/try-runtime",
"polkadot-cli/try-runtime",
"polkadot-service/try-runtime",
"shell-runtime/try-runtime",
@@ -0,0 +1 @@
../../parachains/chain-specs/people-rococo.json
@@ -0,0 +1 @@
../../parachains/chain-specs/people-westend.json
@@ -27,6 +27,7 @@ pub mod contracts;
pub mod coretime;
pub mod glutton;
pub mod penpal;
pub mod people;
pub mod rococo_parachain;
pub mod seedling;
pub mod shell;
@@ -0,0 +1,320 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::chain_spec::GenericChainSpec;
use cumulus_primitives_core::ParaId;
use parachains_common::Balance as PeopleBalance;
use sc_chain_spec::ChainSpec;
use std::str::FromStr;
/// Collects all supported People configurations.
#[derive(Debug, PartialEq)]
pub enum PeopleRuntimeType {
Rococo,
RococoLocal,
RococoDevelopment,
Westend,
WestendLocal,
WestendDevelopment,
}
impl FromStr for PeopleRuntimeType {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
rococo::PEOPLE_ROCOCO => Ok(PeopleRuntimeType::Rococo),
rococo::PEOPLE_ROCOCO_LOCAL => Ok(PeopleRuntimeType::RococoLocal),
rococo::PEOPLE_ROCOCO_DEVELOPMENT => Ok(PeopleRuntimeType::RococoDevelopment),
westend::PEOPLE_WESTEND => Ok(PeopleRuntimeType::Westend),
westend::PEOPLE_WESTEND_LOCAL => Ok(PeopleRuntimeType::WestendLocal),
westend::PEOPLE_WESTEND_DEVELOPMENT => Ok(PeopleRuntimeType::WestendDevelopment),
_ => Err(format!("Value '{}' is not configured yet", value)),
}
}
}
impl PeopleRuntimeType {
pub const ID_PREFIX: &'static str = "people";
pub fn load_config(&self) -> Result<Box<dyn ChainSpec>, String> {
match self {
PeopleRuntimeType::Rococo => Ok(Box::new(GenericChainSpec::from_json_bytes(
&include_bytes!("../../chain-specs/people-rococo.json")[..],
)?)),
PeopleRuntimeType::RococoLocal => Ok(Box::new(rococo::local_config(
rococo::PEOPLE_ROCOCO_LOCAL,
"Rococo People Local",
"rococo-local",
ParaId::new(1004),
))),
PeopleRuntimeType::RococoDevelopment => Ok(Box::new(rococo::local_config(
rococo::PEOPLE_ROCOCO_DEVELOPMENT,
"Rococo People Development",
"rococo-development",
ParaId::new(1004),
))),
PeopleRuntimeType::Westend => Ok(Box::new(GenericChainSpec::from_json_bytes(
&include_bytes!("../../chain-specs/people-westend.json")[..],
)?)),
PeopleRuntimeType::WestendLocal => Ok(Box::new(westend::local_config(
westend::PEOPLE_WESTEND_LOCAL,
"Westend People Local",
"westend-local",
ParaId::new(1004),
))),
PeopleRuntimeType::WestendDevelopment => Ok(Box::new(westend::local_config(
westend::PEOPLE_WESTEND_DEVELOPMENT,
"Westend People Development",
"westend-development",
ParaId::new(1004),
))),
}
}
}
/// Check if `id` satisfies People-like format.
fn ensure_id(id: &str) -> Result<&str, String> {
if id.starts_with(PeopleRuntimeType::ID_PREFIX) {
Ok(id)
} else {
Err(format!(
"Invalid 'id' attribute ({}), should start with prefix: {}",
id,
PeopleRuntimeType::ID_PREFIX
))
}
}
/// Sub-module for Rococo setup.
pub mod rococo {
use super::{ParaId, PeopleBalance};
use crate::chain_spec::{
get_account_id_from_seed, get_collator_keys_from_seed, Extensions, GenericChainSpec,
SAFE_XCM_VERSION,
};
use parachains_common::{rococo::currency::EXISTENTIAL_DEPOSIT, AccountId, AuraId};
use sc_chain_spec::ChainType;
use sp_core::sr25519;
pub(crate) const PEOPLE_ROCOCO: &str = "people-rococo";
pub(crate) const PEOPLE_ROCOCO_LOCAL: &str = "people-rococo-local";
pub(crate) const PEOPLE_ROCOCO_DEVELOPMENT: &str = "people-rococo-development";
const PEOPLE_ROCOCO_ED: PeopleBalance = EXISTENTIAL_DEPOSIT;
pub fn local_config(
id: &str,
chain_name: &str,
relay_chain: &str,
para_id: ParaId,
) -> GenericChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("ss58Format".into(), 42.into());
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
GenericChainSpec::builder(
people_rococo_runtime::WASM_BINARY
.expect("WASM binary was not built, please build it!"),
Extensions { relay_chain: relay_chain.to_string(), para_id: para_id.into() },
)
.with_name(chain_name)
.with_id(super::ensure_id(id).expect("invalid id"))
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
para_id,
))
.with_properties(properties)
.build()
}
fn genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> serde_json::Value {
serde_json::json!({
"balances": {
"balances": endowed_accounts
.iter()
.cloned()
.map(|k| (k, PEOPLE_ROCOCO_ED * 524_288))
.collect::<Vec<_>>(),
},
"parachainInfo": {
"parachainId": id,
},
"collatorSelection": {
"invulnerables": invulnerables
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect::<Vec<_>>(),
"candidacyBond": PEOPLE_ROCOCO_ED * 16,
},
"session": {
"keys": invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
people_rococo_runtime::SessionKeys { aura }, // session keys
)
})
.collect::<Vec<_>>(),
},
"polkadotXcm": {
"safeXcmVersion": Some(SAFE_XCM_VERSION),
}
})
}
}
/// Sub-module for Westend setup.
pub mod westend {
use super::{ParaId, PeopleBalance};
use crate::chain_spec::{
get_account_id_from_seed, get_collator_keys_from_seed, Extensions, GenericChainSpec,
SAFE_XCM_VERSION,
};
use parachains_common::{westend::currency::EXISTENTIAL_DEPOSIT, AccountId, AuraId};
use sc_chain_spec::ChainType;
use sp_core::sr25519;
pub(crate) const PEOPLE_WESTEND: &str = "people-westend";
pub(crate) const PEOPLE_WESTEND_LOCAL: &str = "people-westend-local";
pub(crate) const PEOPLE_WESTEND_DEVELOPMENT: &str = "people-westend-development";
const PEOPLE_WESTEND_ED: PeopleBalance = EXISTENTIAL_DEPOSIT;
pub fn local_config(
id: &str,
chain_name: &str,
relay_chain: &str,
para_id: ParaId,
) -> GenericChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("ss58Format".into(), 42.into());
properties.insert("tokenSymbol".into(), "WND".into());
properties.insert("tokenDecimals".into(), 12.into());
GenericChainSpec::builder(
people_westend_runtime::WASM_BINARY
.expect("WASM binary was not built, please build it!"),
Extensions { relay_chain: relay_chain.to_string(), para_id: para_id.into() },
)
.with_name(chain_name)
.with_id(super::ensure_id(id).expect("invalid id"))
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
para_id,
))
.with_properties(properties)
.build()
}
fn genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> serde_json::Value {
serde_json::json!({
"balances": {
"balances": endowed_accounts
.iter()
.cloned()
.map(|k| (k, PEOPLE_WESTEND_ED * 524_288))
.collect::<Vec<_>>(),
},
"parachainInfo": {
"parachainId": id,
},
"collatorSelection": {
"invulnerables": invulnerables
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect::<Vec<_>>(),
"candidacyBond": PEOPLE_WESTEND_ED * 16,
},
"session": {
"keys": invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
people_westend_runtime::SessionKeys { aura }, // session keys
)
})
.collect::<Vec<_>>(),
},
"polkadotXcm": {
"safeXcmVersion": Some(SAFE_XCM_VERSION),
}
})
}
}
+52 -55
View File
@@ -56,6 +56,7 @@ enum Runtime {
GluttonWestend,
BridgeHub(chain_spec::bridge_hubs::BridgeHubRuntimeType),
Coretime(chain_spec::coretime::CoretimeRuntimeType),
People(chain_spec::people::PeopleRuntimeType),
}
trait RuntimeResolver {
@@ -122,6 +123,8 @@ fn runtime(id: &str) -> Runtime {
Runtime::GluttonWestend
} else if id.starts_with("glutton") {
Runtime::Glutton
} else if id.starts_with(chain_spec::people::PeopleRuntimeType::ID_PREFIX) {
Runtime::People(id.parse::<chain_spec::people::PeopleRuntimeType>().expect("Invalid value"))
} else {
log::warn!("No specific runtime was recognized for ChainSpec's id: '{}', so Runtime::default() will be used", id);
Runtime::default()
@@ -247,6 +250,14 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn ChainSpec>, String> {
para_id.expect("Must specify parachain id"),
)),
// -- People
people_like_id
if people_like_id.starts_with(chain_spec::people::PeopleRuntimeType::ID_PREFIX) =>
people_like_id
.parse::<chain_spec::people::PeopleRuntimeType>()
.expect("invalid value")
.load_config()?,
// -- Fallback (generic chainspec)
"" => {
log::warn!("No ChainSpec.id specified, so using default one, based on rococo-parachain runtime");
@@ -397,7 +408,8 @@ macro_rules! construct_partials {
Runtime::BridgeHub(_) |
Runtime::CollectivesPolkadot |
Runtime::CollectivesWestend |
Runtime::Coretime(_) => {
Runtime::Coretime(_) |
Runtime::People(_) => {
let $partials = new_partial::<RuntimeApi, _>(
&$config,
crate::service::aura_build_import_queue::<_, AuraId>,
@@ -449,7 +461,8 @@ macro_rules! construct_async_run {
Runtime::BridgeHub(_) |
Runtime::CollectivesPolkadot |
Runtime::CollectivesWestend |
Runtime::Coretime(_) => {
Runtime::Coretime(_) |
Runtime::People(_) => {
runner.async_run(|$config| {
let $components = new_partial::<RuntimeApi, _>(
&$config,
@@ -501,6 +514,7 @@ macro_rules! construct_async_run {
/// Parse command line arguments into service configuration.
pub fn run() -> Result<()> {
use Runtime::*;
let cli = Cli::from_args();
match &cli.subcommand {
@@ -673,35 +687,26 @@ pub fn run() -> Result<()> {
info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
match config.chain_spec.runtime() {
Runtime::AssetHubPolkadot => crate::service::start_asset_hub_node::<
AssetHubPolkadot => crate::service::start_asset_hub_node::<
AssetHubPolkadotRuntimeApi,
AssetHubPolkadotAuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::AssetHubKusama => crate::service::start_asset_hub_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::AssetHubRococo => crate::service::start_asset_hub_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
AssetHubKusama |
AssetHubRococo |
AssetHubWestend =>
crate::service::start_asset_hub_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::AssetHubWestend => crate::service::start_asset_hub_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::CollectivesPolkadot =>
CollectivesPolkadot | CollectivesWestend =>
crate::service::start_generic_aura_node::<
RuntimeApi,
AuraId,
@@ -709,15 +714,8 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::CollectivesWestend =>
crate::service::start_generic_aura_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::Shell =>
Seedling | Shell =>
crate::service::start_shell_node::<RuntimeApi>(
config,
polkadot_config,
@@ -728,18 +726,8 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::Seedling =>
crate::service::start_shell_node::<RuntimeApi>(
config,
polkadot_config,
collator_options,
id,
hwbench
)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::ContractsRococo => crate::service::start_contracts_rococo_node(
ContractsRococo => crate::service::start_contracts_rococo_node(
config,
polkadot_config,
collator_options,
@@ -750,7 +738,7 @@ pub fn run() -> Result<()> {
.map(|r| r.0)
.map_err(Into::into),
Runtime::BridgeHub(bridge_hub_runtime_type) => match bridge_hub_runtime_type {
BridgeHub(bridge_hub_runtime_type) => match bridge_hub_runtime_type {
chain_spec::bridge_hubs::BridgeHubRuntimeType::Polkadot =>
crate::service::start_generic_aura_node::<
RuntimeApi,
@@ -786,7 +774,7 @@ pub fn run() -> Result<()> {
}
.map_err(Into::into),
Runtime::Coretime(coretime_runtime_type) => match coretime_runtime_type {
Coretime(coretime_runtime_type) => match coretime_runtime_type {
chain_spec::coretime::CoretimeRuntimeType::Rococo |
chain_spec::coretime::CoretimeRuntimeType::RococoLocal |
chain_spec::coretime::CoretimeRuntimeType::RococoDevelopment |
@@ -801,7 +789,7 @@ pub fn run() -> Result<()> {
}
.map_err(Into::into),
Runtime::Penpal(_) | Runtime::Default =>
Penpal(_) | Default =>
crate::service::start_rococo_parachain_node(
config,
polkadot_config,
@@ -812,15 +800,8 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::GluttonWestend =>
crate::service::start_basic_lookahead_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0)
.map_err(Into::into),
Runtime::Glutton =>
Glutton | GluttonWestend =>
crate::service::start_basic_lookahead_node::<
RuntimeApi,
AuraId,
@@ -828,6 +809,22 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into),
People(people_runtime_type) => match people_runtime_type {
chain_spec::people::PeopleRuntimeType::Rococo |
chain_spec::people::PeopleRuntimeType::RococoLocal |
chain_spec::people::PeopleRuntimeType::RococoDevelopment |
chain_spec::people::PeopleRuntimeType::Westend |
chain_spec::people::PeopleRuntimeType::WestendLocal |
chain_spec::people::PeopleRuntimeType::WestendDevelopment =>
crate::service::start_generic_aura_node::<
RuntimeApi,
AuraId,
>(config, polkadot_config, collator_options, id, hwbench)
.await
.map(|r| r.0),
}
.map_err(Into::into),
}
})
},
+24 -3
View File
@@ -98,7 +98,6 @@ impl sc_executor::NativeExecutionDispatch for ShellRuntimeExecutor {
/// Native Asset Hub Westend (Westmint) executor instance.
pub struct AssetHubWestendExecutor;
impl sc_executor::NativeExecutionDispatch for AssetHubWestendExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
@@ -128,7 +127,6 @@ impl sc_executor::NativeExecutionDispatch for CollectivesWestendRuntimeExecutor
/// Native BridgeHubRococo executor instance.
pub struct BridgeHubRococoRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for BridgeHubRococoRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
@@ -167,7 +165,6 @@ impl sc_executor::NativeExecutionDispatch for CoretimeWestendRuntimeExecutor {
/// Native contracts executor instance.
pub struct ContractsRococoRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for ContractsRococoRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
@@ -195,6 +192,30 @@ impl sc_executor::NativeExecutionDispatch for GluttonWestendRuntimeExecutor {
}
}
/// Native `PeopleWestend` executor instance.
pub struct PeopleWestendRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for PeopleWestendRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
people_westend_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
people_westend_runtime::native_version()
}
}
/// Native `PeopleRococo` executor instance.
pub struct PeopleRococoRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for PeopleRococoRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
people_rococo_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
people_rococo_runtime::native_version()
}
}
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to