Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • nodes/rust/duniter-v2s
  • llaq/lc-core-substrate
  • pini-gh/duniter-v2s
  • vincentux/duniter-v2s
  • mildred/duniter-v2s
  • d0p1/duniter-v2s
  • bgallois/duniter-v2s
  • Nicolas80/duniter-v2s
8 results
Show changes
Showing
with 2048 additions and 604 deletions
...@@ -14,15 +14,17 @@ ...@@ -14,15 +14,17 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
#[cfg(feature = "g1")]
pub mod g1; pub mod g1;
#[cfg(feature = "gdev")]
pub mod gdev; pub mod gdev;
#[cfg(feature = "gtest")]
pub mod gtest; pub mod gtest;
use common_runtime::IdtyIndex; use common_runtime::{AccountId, IdtyIndex, Signature};
use common_runtime::{entities::IdtyName, AccountId, Signature};
use sp_core::{Pair, Public}; use sp_core::{Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify}; use sp_runtime::traits::{IdentifyAccount, Verify};
use std::collections::{BTreeMap, BTreeSet}; use std::collections::BTreeMap;
pub type AccountPublic = <Signature as Verify>::Signer; pub type AccountPublic = <Signature as Verify>::Signer;
...@@ -49,20 +51,24 @@ where ...@@ -49,20 +51,24 @@ where
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account() AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
} }
fn clique_wot(initial_identities_len: usize) -> BTreeMap<IdtyIndex, BTreeSet<IdtyIndex>> { fn clique_wot(
initial_identities_len: usize,
cert_validity_period: common_runtime::BlockNumber,
) -> BTreeMap<IdtyIndex, BTreeMap<IdtyIndex, common_runtime::BlockNumber>> {
let mut certs_by_issuer = BTreeMap::new(); let mut certs_by_issuer = BTreeMap::new();
for i in 1..=initial_identities_len { for i in 1..=initial_identities_len {
certs_by_issuer.insert( certs_by_issuer.insert(
i as IdtyIndex, i as IdtyIndex,
(1..=initial_identities_len) (1..=initial_identities_len)
.filter_map(|j| if i != j { Some(j as IdtyIndex) } else { None }) .filter_map(|j| {
if i != j {
Some((j as IdtyIndex, cert_validity_period))
} else {
None
}
})
.collect(), .collect(),
); );
} }
certs_by_issuer certs_by_issuer
} }
/// Create a fake IdtyName (for dev and testnet)
fn idty_name(u8_: u8) -> IdtyName {
IdtyName(vec![u8_])
}
...@@ -18,13 +18,14 @@ use super::*; ...@@ -18,13 +18,14 @@ use super::*;
use common_runtime::entities::IdtyName; use common_runtime::entities::IdtyName;
use gdev_runtime::{ use gdev_runtime::{
AccountId, BalancesConfig, GenesisConfig, GrandpaConfig, IdentityConfig, IdtyRight, IdtyValue, AccountId, BalancesConfig, GenesisConfig, GrandpaConfig, IdentityConfig, IdtyRight, IdtyValue,
StrongCertConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, MembershipConfig, StrongCertConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig,
WASM_BINARY, UniversalDividendConfig, WASM_BINARY,
}; };
use maplit::btreemap; use maplit::btreemap;
use sc_service::ChainType; use sc_service::ChainType;
use sp_core::sr25519; use sp_core::sr25519;
use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_finality_grandpa::AuthorityId as GrandpaId;
use sp_membership::MembershipData;
use std::collections::BTreeMap; use std::collections::BTreeMap;
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>; pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
...@@ -34,12 +35,9 @@ const TOKEN_SYMBOL: &str = "ĞD"; ...@@ -34,12 +35,9 @@ const TOKEN_SYMBOL: &str = "ĞD";
// The URL for the telemetry server. // The URL for the telemetry server.
// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
/// Generate an Aura authority key. /// Generate an authority keys.
pub fn authority_keys_from_seed(s: &str) -> (sp_consensus_aura::sr25519::AuthorityId, GrandpaId) { pub fn get_authority_keys_from_seed(s: &str) -> GrandpaId {
( get_from_seed::<GrandpaId>(s)
get_from_seed::<sp_consensus_aura::sr25519::AuthorityId>(s),
get_from_seed::<GrandpaId>(s),
)
} }
pub fn development_chain_spec() -> Result<ChainSpec, String> { pub fn development_chain_spec() -> Result<ChainSpec, String> {
...@@ -54,13 +52,13 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> { ...@@ -54,13 +52,13 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
move || { move || {
devnet_genesis( devnet_genesis(
wasm_binary, wasm_binary,
// Initial PoA authorities // Initial authorities
vec![authority_keys_from_seed("Alice")], vec![get_authority_keys_from_seed("Alice")],
// Inital identities // Inital identities
btreemap![ btreemap![
idty_name(1) => get_account_id_from_seed::<sr25519::Public>("Alice"), IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
idty_name(2) => get_account_id_from_seed::<sr25519::Public>("Bob"), IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
idty_name(3) => get_account_id_from_seed::<sr25519::Public>("Charlie"), IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
], ],
// Sudo account // Sudo account
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
...@@ -90,7 +88,7 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> { ...@@ -90,7 +88,7 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
fn devnet_genesis( fn devnet_genesis(
wasm_binary: &[u8], wasm_binary: &[u8],
initial_authorities: Vec<(sp_consensus_aura::sr25519::AuthorityId, GrandpaId)>, initial_authorities: Vec<GrandpaId>,
initial_identities: BTreeMap<IdtyName, AccountId>, initial_identities: BTreeMap<IdtyName, AccountId>,
root_key: AccountId, root_key: AccountId,
_enable_println: bool, _enable_println: bool,
...@@ -104,10 +102,7 @@ fn devnet_genesis( ...@@ -104,10 +102,7 @@ fn devnet_genesis(
balances: Default::default(), balances: Default::default(),
}, },
grandpa: GrandpaConfig { grandpa: GrandpaConfig {
authorities: initial_authorities authorities: initial_authorities.iter().map(|x| (x.clone(), 1)).collect(),
.iter()
.map(|x| (x.1.clone(), 1))
.collect(),
}, },
sudo: SudoConfig { sudo: SudoConfig {
// Assign network admin rights. // Assign network admin rights.
...@@ -117,24 +112,38 @@ fn devnet_genesis( ...@@ -117,24 +112,38 @@ fn devnet_genesis(
identities: initial_identities identities: initial_identities
.iter() .iter()
.map(|(name, account)| IdtyValue { .map(|(name, account)| IdtyValue {
name: name.clone(), data: Default::default(),
expire_on: gdev_runtime::MaxInactivityPeriod::get(),
owner_key: account.clone(), owner_key: account.clone(),
name: name.clone(),
next_creatable_identity_on: Default::default(),
removable_on: 0, removable_on: 0,
renewable_on: gdev_runtime::StrongCertRenewablePeriod::get(),
rights: vec![ rights: vec![
(IdtyRight::CreateIdty, None), (IdtyRight::CreateIdty, None),
(IdtyRight::StrongCert, None), (IdtyRight::StrongCert, None),
(IdtyRight::Ud, None), (IdtyRight::Ud, None),
], ],
status: gdev_runtime::IdtyStatus::Validated, status: gdev_runtime::IdtyStatus::Validated,
data: Default::default(), })
.collect(),
},
membership: MembershipConfig {
memberships: (1..=initial_identities.len())
.map(|i| {
(
i as u32,
MembershipData {
expire_on: gdev_runtime::MembershipPeriod::get(),
renewable_on: gdev_runtime::RenewablePeriod::get(),
},
)
}) })
.collect(), .collect(),
}, },
strong_cert: StrongCertConfig { strong_cert: StrongCertConfig {
certs_by_issuer: clique_wot(initial_identities.len()), certs_by_issuer: clique_wot(
phantom: std::marker::PhantomData, initial_identities.len(),
gdev_runtime::parameters::ValidityPeriod::get(),
),
}, },
ud_accounts_storage: UdAccountsStorageConfig { ud_accounts_storage: UdAccountsStorageConfig {
ud_accounts: initial_identities.values().cloned().collect(), ud_accounts: initial_identities.values().cloned().collect(),
......
...@@ -15,19 +15,30 @@ ...@@ -15,19 +15,30 @@
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use super::*; use super::*;
use common_runtime::constants::*;
use common_runtime::entities::IdtyName; use common_runtime::entities::IdtyName;
use gtest_runtime::{ use gtest_runtime::{
AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, IdentityConfig, IdtyRight, opaque::SessionKeys, AccountId, BabeConfig, BalancesConfig, GenesisConfig, IdentityConfig,
IdtyValue, StrongCertConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig, IdtyRight, IdtyValue, ImOnlineId, MembershipConfig, SessionConfig, StrongCertConfig,
UniversalDividendConfig, WASM_BINARY, SudoConfig, SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY,
}; };
use maplit::btreemap; use maplit::btreemap;
use sc_service::ChainType; use sc_service::ChainType;
use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_core::sr25519; use sp_core::sr25519;
use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_finality_grandpa::AuthorityId as GrandpaId;
use sp_membership::MembershipData;
use std::collections::BTreeMap; use std::collections::BTreeMap;
pub type AuthorityKeys = (
AccountId,
BabeId,
GrandpaId,
ImOnlineId,
AuthorityDiscoveryId,
);
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>; pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
const TOKEN_DECIMALS: usize = 2; const TOKEN_DECIMALS: usize = 2;
...@@ -35,13 +46,105 @@ const TOKEN_SYMBOL: &str = "ĞT"; ...@@ -35,13 +46,105 @@ const TOKEN_SYMBOL: &str = "ĞT";
// The URL for the telemetry server. // The URL for the telemetry server.
// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
/// Generate an Aura authority key. /// Generate an authority keys.
pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { pub fn get_authority_keys_from_seed(s: &str) -> AuthorityKeys {
(get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s)) (
get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<BabeId>(s),
get_from_seed::<GrandpaId>(s),
get_from_seed::<ImOnlineId>(s),
get_from_seed::<AuthorityDiscoveryId>(s),
)
}
fn devnet_genesis(
wasm_binary: &[u8],
initial_authorities: Vec<AuthorityKeys>,
initial_identities: BTreeMap<IdtyName, AccountId>,
root_key: AccountId,
_enable_println: bool,
) -> GenesisConfig {
GenesisConfig {
system: SystemConfig {
// Add Wasm runtime to storage.
code: wasm_binary.to_vec(),
},
authority_discovery: Default::default(),
balances: BalancesConfig {
// Configure endowed accounts with initial balance of INITIAL_BALANCE.
balances: Vec::with_capacity(0),
},
babe: BabeConfig {
authorities: Vec::with_capacity(0),
epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG),
},
grandpa: Default::default(),
im_online: Default::default(),
session: SessionConfig {
keys: initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()),
)
})
.collect::<Vec<_>>(),
},
sudo: SudoConfig {
// Assign network admin rights.
key: Some(root_key),
},
identity: IdentityConfig {
identities: initial_identities
.iter()
.map(|(name, account)| IdtyValue {
data: Default::default(),
name: name.clone(),
next_creatable_identity_on: Default::default(),
owner_key: account.clone(),
removable_on: 0,
rights: vec![
(IdtyRight::CreateIdty, None),
(IdtyRight::StrongCert, None),
(IdtyRight::Ud, None),
],
status: gtest_runtime::IdtyStatus::Validated,
})
.collect(),
},
membership: MembershipConfig {
memberships: (1..=initial_identities.len())
.map(|i| {
(
i as u32,
MembershipData {
expire_on: gtest_runtime::MembershipPeriod::get(),
renewable_on: gtest_runtime::RenewablePeriod::get(),
},
)
})
.collect(),
},
strong_cert: StrongCertConfig {
certs_by_issuer: clique_wot(
initial_identities.len(),
gtest_runtime::parameters::ValidityPeriod::get(),
),
},
ud_accounts_storage: UdAccountsStorageConfig {
ud_accounts: initial_identities.values().cloned().collect(),
},
universal_dividend: UniversalDividendConfig {
first_ud: 1_000,
initial_monetary_mass: 0,
},
}
} }
pub fn development_chain_spec() -> Result<ChainSpec, String> { pub fn development_chain_spec() -> Result<ChainSpec, String> {
let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?;
Ok(ChainSpec::from_genesis( Ok(ChainSpec::from_genesis(
// Name // Name
...@@ -53,12 +156,12 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> { ...@@ -53,12 +156,12 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
devnet_genesis( devnet_genesis(
wasm_binary, wasm_binary,
// Initial PoA authorities // Initial PoA authorities
vec![authority_keys_from_seed("Alice")], vec![get_authority_keys_from_seed("Alice")],
// Inital identities // Inital identities
btreemap![ btreemap![
idty_name(1) => get_account_id_from_seed::<sr25519::Public>("Alice"), IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
idty_name(2) => get_account_id_from_seed::<sr25519::Public>("Bob"), IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
idty_name(3) => get_account_id_from_seed::<sr25519::Public>("Charlie"), IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
], ],
// Sudo account // Sudo account
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
...@@ -86,8 +189,18 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> { ...@@ -86,8 +189,18 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
)) ))
} }
pub fn local_testnet_config() -> Result<ChainSpec, String> { pub fn local_testnet_config(authorities_count: usize) -> Result<ChainSpec, String> {
let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?;
let mut authorities = vec![
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
get_authority_keys_from_seed("Dave"),
get_authority_keys_from_seed("Eve"),
get_authority_keys_from_seed("Ferdie"),
];
authorities.truncate(authorities_count);
Ok(ChainSpec::from_genesis( Ok(ChainSpec::from_genesis(
// Name // Name
...@@ -98,19 +211,16 @@ pub fn local_testnet_config() -> Result<ChainSpec, String> { ...@@ -98,19 +211,16 @@ pub fn local_testnet_config() -> Result<ChainSpec, String> {
move || { move || {
testnet_genesis( testnet_genesis(
wasm_binary, wasm_binary,
// Initial PoA authorities // Initial authorities
vec![ authorities.clone(),
authority_keys_from_seed("Alice"),
authority_keys_from_seed("Bob"),
],
// Initial identities // Initial identities
btreemap![ btreemap![
idty_name(1) => get_account_id_from_seed::<sr25519::Public>("Alice"), IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
idty_name(2) => get_account_id_from_seed::<sr25519::Public>("Bob"), IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
idty_name(3) => get_account_id_from_seed::<sr25519::Public>("Charlie"), IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
idty_name(4) => get_account_id_from_seed::<sr25519::Public>("Dave"), IdtyName::from("Dave") => get_account_id_from_seed::<sr25519::Public>("Dave"),
idty_name(5) => get_account_id_from_seed::<sr25519::Public>("Eve"), IdtyName::from("Eve") => get_account_id_from_seed::<sr25519::Public>("Eve"),
idty_name(6) => get_account_id_from_seed::<sr25519::Public>("Ferdie"), IdtyName::from("Ferdie") => get_account_id_from_seed::<sr25519::Public>("Ferdie"),
], ],
// Sudo account // Sudo account
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
...@@ -138,71 +248,23 @@ pub fn local_testnet_config() -> Result<ChainSpec, String> { ...@@ -138,71 +248,23 @@ pub fn local_testnet_config() -> Result<ChainSpec, String> {
)) ))
} }
fn devnet_genesis( fn session_keys(
wasm_binary: &[u8], babe: BabeId,
initial_authorities: Vec<(AuraId, GrandpaId)>, grandpa: GrandpaId,
initial_identities: BTreeMap<IdtyName, AccountId>, im_online: ImOnlineId,
root_key: AccountId, authority_discovery: AuthorityDiscoveryId,
_enable_println: bool, ) -> SessionKeys {
) -> GenesisConfig { SessionKeys {
GenesisConfig { babe,
system: SystemConfig { grandpa,
// Add Wasm runtime to storage. im_online,
code: wasm_binary.to_vec(), authority_discovery,
},
balances: BalancesConfig {
// Configure endowed accounts with initial balance of INITIAL_BALANCE.
balances: Vec::with_capacity(0),
},
aura: AuraConfig {
authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),
},
grandpa: GrandpaConfig {
authorities: initial_authorities
.iter()
.map(|x| (x.1.clone(), 1))
.collect(),
},
sudo: SudoConfig {
// Assign network admin rights.
key: Some(root_key),
},
identity: IdentityConfig {
identities: initial_identities
.iter()
.map(|(name, account)| IdtyValue {
name: name.clone(),
expire_on: gtest_runtime::MaxInactivityPeriod::get(),
owner_key: account.clone(),
removable_on: 0,
renewable_on: gtest_runtime::StrongCertRenewablePeriod::get(),
rights: vec![
(IdtyRight::CreateIdty, None),
(IdtyRight::StrongCert, None),
(IdtyRight::Ud, None),
],
status: gtest_runtime::IdtyStatus::Validated,
data: Default::default(),
})
.collect(),
},
strong_cert: StrongCertConfig {
certs_by_issuer: clique_wot(initial_identities.len()),
phantom: std::marker::PhantomData,
},
ud_accounts_storage: UdAccountsStorageConfig {
ud_accounts: initial_identities.values().cloned().collect(),
},
universal_dividend: UniversalDividendConfig {
first_ud: 1_000,
initial_monetary_mass: 0,
},
} }
} }
fn testnet_genesis( fn testnet_genesis(
wasm_binary: &[u8], wasm_binary: &[u8],
initial_authorities: Vec<(AuraId, GrandpaId)>, initial_authorities: Vec<AuthorityKeys>,
initial_identities: BTreeMap<IdtyName, AccountId>, initial_identities: BTreeMap<IdtyName, AccountId>,
root_key: AccountId, root_key: AccountId,
_enable_println: bool, _enable_println: bool,
...@@ -212,18 +274,28 @@ fn testnet_genesis( ...@@ -212,18 +274,28 @@ fn testnet_genesis(
// Add Wasm runtime to storage. // Add Wasm runtime to storage.
code: wasm_binary.to_vec(), code: wasm_binary.to_vec(),
}, },
authority_discovery: Default::default(),
balances: BalancesConfig { balances: BalancesConfig {
// Configure endowed accounts with initial balance of INITIAL_BALANCE. // Configure endowed accounts with initial balance of INITIAL_BALANCE.
balances: Vec::with_capacity(0), balances: Vec::with_capacity(0),
}, },
aura: AuraConfig { babe: BabeConfig {
authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), authorities: Vec::with_capacity(0),
epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG),
}, },
grandpa: GrandpaConfig { grandpa: Default::default(),
authorities: initial_authorities im_online: Default::default(),
session: SessionConfig {
keys: initial_authorities
.iter() .iter()
.map(|x| (x.1.clone(), 1)) .map(|x| {
.collect(), (
x.0.clone(),
x.0.clone(),
session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()),
)
})
.collect::<Vec<_>>(),
}, },
sudo: SudoConfig { sudo: SudoConfig {
// Assign network admin rights. // Assign network admin rights.
...@@ -233,24 +305,38 @@ fn testnet_genesis( ...@@ -233,24 +305,38 @@ fn testnet_genesis(
identities: initial_identities identities: initial_identities
.iter() .iter()
.map(|(name, account)| IdtyValue { .map(|(name, account)| IdtyValue {
data: Default::default(),
name: name.clone(), name: name.clone(),
expire_on: gtest_runtime::MaxInactivityPeriod::get(), next_creatable_identity_on: Default::default(),
owner_key: account.clone(), owner_key: account.clone(),
removable_on: 0, removable_on: 0,
renewable_on: gtest_runtime::StrongCertRenewablePeriod::get(),
rights: vec![ rights: vec![
(IdtyRight::CreateIdty, None), (IdtyRight::CreateIdty, None),
(IdtyRight::StrongCert, None), (IdtyRight::StrongCert, None),
(IdtyRight::Ud, None), (IdtyRight::Ud, None),
], ],
status: gtest_runtime::IdtyStatus::Validated, status: gtest_runtime::IdtyStatus::Validated,
data: Default::default(), })
.collect(),
},
membership: MembershipConfig {
memberships: (1..=initial_identities.len())
.map(|i| {
(
i as u32,
MembershipData {
expire_on: gtest_runtime::MembershipPeriod::get(),
renewable_on: gtest_runtime::RenewablePeriod::get(),
},
)
}) })
.collect(), .collect(),
}, },
strong_cert: StrongCertConfig { strong_cert: StrongCertConfig {
certs_by_issuer: clique_wot(initial_identities.len()), certs_by_issuer: clique_wot(
phantom: std::marker::PhantomData, initial_identities.len(),
gtest_runtime::parameters::ValidityPeriod::get(),
),
}, },
ud_accounts_storage: UdAccountsStorageConfig { ud_accounts_storage: UdAccountsStorageConfig {
ud_accounts: initial_identities.values().cloned().collect(), ud_accounts: initial_identities.values().cloned().collect(),
......
...@@ -16,9 +16,14 @@ ...@@ -16,9 +16,14 @@
// limitations under the License. // limitations under the License.
use crate::cli::{Cli, Subcommand}; use crate::cli::{Cli, Subcommand};
use crate::service::{G1Executor, GDevExecutor, GTestExecutor, IdentifyVariant}; #[cfg(feature = "g1")]
use crate::service::G1Executor;
#[cfg(feature = "gdev")]
use crate::service::GDevExecutor;
#[cfg(feature = "gtest")]
use crate::service::GTestExecutor;
use crate::service::{IdentifyRuntimeType, RuntimeType};
use crate::{chain_spec, service}; use crate::{chain_spec, service};
use gdev_runtime::Block;
use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
impl SubstrateCli for Cli { impl SubstrateCli for Cli {
...@@ -48,9 +53,14 @@ impl SubstrateCli for Cli { ...@@ -48,9 +53,14 @@ impl SubstrateCli for Cli {
fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> { fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
Ok(match id { Ok(match id {
#[cfg(feature = "gdev")]
"dev" | "gdev" => Box::new(chain_spec::gdev::development_chain_spec()?), "dev" | "gdev" => Box::new(chain_spec::gdev::development_chain_spec()?),
#[cfg(feature = "gtest")]
"gtest_dev" => Box::new(chain_spec::gtest::development_chain_spec()?), "gtest_dev" => Box::new(chain_spec::gtest::development_chain_spec()?),
"local" | "gtest_local" => Box::new(chain_spec::gtest::local_testnet_config()?), #[cfg(feature = "gtest")]
"local" | "gtest_local" => Box::new(chain_spec::gtest::local_testnet_config(2)?),
#[cfg(feature = "gtest")]
"local4" | "gtest_local4" => Box::new(chain_spec::gtest::local_testnet_config(4)?),
// Specs provided as json specify which runtime to use in their file name. For example, // Specs provided as json specify which runtime to use in their file name. For example,
// `g1-custom.json` uses the g1 runtime. // `g1-custom.json` uses the g1 runtime.
// `gdev-workshop.json` uses the gdev runtime. // `gdev-workshop.json` uses the gdev runtime.
...@@ -64,28 +74,44 @@ impl SubstrateCli for Cli { ...@@ -64,28 +74,44 @@ impl SubstrateCli for Cli {
.unwrap_or(false) .unwrap_or(false)
}; };
if starts_with("g1") { let runtime_type = if starts_with("g1") {
Box::new(chain_spec::g1::ChainSpec::from_json_file(path)?) RuntimeType::G1
} else if starts_with("gtest") { } else if starts_with("gdem") {
Box::new(chain_spec::gtest::ChainSpec::from_json_file(path)?) RuntimeType::GTest
} else if starts_with("gdev") { } else if starts_with("dev") || starts_with("gdev") {
Box::new(chain_spec::gdev::ChainSpec::from_json_file(path)?) RuntimeType::GDev
} else if starts_with("gt") {
RuntimeType::GTest
} else { } else {
panic!("unknown runtime") panic!("unknown runtime")
};
match runtime_type {
#[cfg(feature = "g1")]
RuntimeType::G1 => Box::new(chain_spec::g1::ChainSpec::from_json_file(path)?),
#[cfg(feature = "gdev")]
RuntimeType::GDev => {
Box::new(chain_spec::gdev::ChainSpec::from_json_file(path)?)
}
#[cfg(feature = "gtest")]
RuntimeType::GTest => {
Box::new(chain_spec::gtest::ChainSpec::from_json_file(path)?)
}
_ => panic!("unknown runtime"),
} }
} }
}) })
} }
fn native_runtime_version(spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion { fn native_runtime_version(spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
if spec.is_main() { match spec.runtime_type() {
todo!() //return &g1_runtime::VERSION; #[cfg(feature = "g1")]
} else if spec.is_test() { RuntimeType::G1 => &g1_runtime::VERSION,
&gtest_runtime::VERSION #[cfg(feature = "gtest")]
} else if spec.is_dev() { RuntimeType::GTest => &gtest_runtime::VERSION,
&gdev_runtime::VERSION #[cfg(feature = "gdev")]
} else { RuntimeType::GDev => &gdev_runtime::VERSION,
panic!("unknown runtime") _ => panic!("unknown runtime"),
} }
} }
} }
...@@ -100,23 +126,23 @@ pub fn run() -> sc_cli::Result<()> { ...@@ -100,23 +126,23 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| { runner.sync_run(|config| {
if cmd.shared_params.dev { if cmd.shared_params.dev {
if config.chain_spec.is_main() { match config.chain_spec.runtime_type() {
cmd.run( #[cfg(feature = "g1")]
RuntimeType::G1 => cmd.run(
Box::new(chain_spec::g1::development_chain_spec()?), Box::new(chain_spec::g1::development_chain_spec()?),
config.network, config.network,
) ),
} else if config.chain_spec.is_test() { #[cfg(feature = "gtest")]
cmd.run( RuntimeType::GTest => cmd.run(
Box::new(chain_spec::gtest::development_chain_spec()?), Box::new(chain_spec::gtest::development_chain_spec()?),
config.network, config.network,
) ),
} else if config.chain_spec.is_dev() { #[cfg(feature = "gdev")]
cmd.run( RuntimeType::GDev => cmd.run(
Box::new(chain_spec::gdev::development_chain_spec()?), Box::new(chain_spec::gdev::development_chain_spec()?),
config.network, config.network,
) ),
} else { _ => panic!("unknown runtime"),
panic!("unknown runtime")
} }
} else { } else {
cmd.run(config.chain_spec, config.network) cmd.run(config.chain_spec, config.network)
...@@ -167,14 +193,18 @@ pub fn run() -> sc_cli::Result<()> { ...@@ -167,14 +193,18 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
if chain_spec.is_main() { match chain_spec.runtime_type() {
runner.sync_run(|config| cmd.run::<Block, G1Executor>(config)) #[cfg(feature = "g1")]
} else if chain_spec.is_test() { RuntimeType::G1 => {
runner.sync_run(|config| cmd.run::<Block, GTestExecutor>(config)) runner.sync_run(|config| cmd.run::<g1_runtime::Block, G1Executor>(config))
} else if chain_spec.is_dev() { }
runner.sync_run(|config| cmd.run::<Block, GDevExecutor>(config)) #[cfg(feature = "gtest")]
} else { RuntimeType::GTest => runner
unreachable!() .sync_run(|config| cmd.run::<gtest_runtime::Block, GTestExecutor>(config)),
#[cfg(feature = "gdev")]
RuntimeType::GDev => runner
.sync_run(|config| cmd.run::<gdev_runtime::Block, GDevExecutor>(config)),
_ => Err(sc_cli::Error::Application("unknown runtime".into())),
} }
} else { } else {
Err("Benchmarking wasn't enabled when building the node. \ Err("Benchmarking wasn't enabled when building the node. \
...@@ -185,20 +215,26 @@ pub fn run() -> sc_cli::Result<()> { ...@@ -185,20 +215,26 @@ pub fn run() -> sc_cli::Result<()> {
None => { None => {
let runner = cli.create_runner(&cli.run)?; let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move { runner.run_node_until_exit(|config| async move {
if config.chain_spec.is_main() { match config.chain_spec.runtime_type() {
service::new_full::<gtest_runtime::RuntimeApi, G1Executor>(config, None) #[cfg(feature = "g1")]
.map_err(sc_cli::Error::Service) RuntimeType::G1 => {
} else if config.chain_spec.is_test() { service::new_full::<g1_runtime::RuntimeApi, G1Executor>(config, None)
service::new_full::<gtest_runtime::RuntimeApi, GTestExecutor>(config, None) .map_err(sc_cli::Error::Service)
}
#[cfg(feature = "gtest")]
RuntimeType::GTest => {
service::new_full::<gtest_runtime::RuntimeApi, GTestExecutor>(config, None)
.map_err(sc_cli::Error::Service)
}
#[cfg(feature = "gdev")]
RuntimeType::GDev => {
service::new_full::<gdev_runtime::RuntimeApi, GDevExecutor>(
config,
Some(cli.sealing),
)
.map_err(sc_cli::Error::Service) .map_err(sc_cli::Error::Service)
} else if config.chain_spec.is_dev() { }
service::new_full::<gdev_runtime::RuntimeApi, GDevExecutor>( _ => Err(sc_cli::Error::Application("unknown runtime".into())),
config,
Some(cli.sealing),
)
.map_err(sc_cli::Error::Service)
} else {
Err(sc_cli::Error::Application("unknown runtime".into()))
} }
}) })
} }
......
...@@ -23,15 +23,12 @@ use async_io::Timer; ...@@ -23,15 +23,12 @@ use async_io::Timer;
use common_runtime::Block; use common_runtime::Block;
use futures::{Stream, StreamExt}; use futures::{Stream, StreamExt};
use sc_client_api::ExecutorProvider; use sc_client_api::ExecutorProvider;
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
use sc_consensus_manual_seal::{run_manual_seal, EngineCommand, ManualSealParams}; use sc_consensus_manual_seal::{run_manual_seal, EngineCommand, ManualSealParams};
pub use sc_executor::NativeElseWasmExecutor; pub use sc_executor::NativeElseWasmExecutor;
use sc_finality_grandpa::SharedVoterState; use sc_finality_grandpa::SharedVoterState;
use sc_keystore::LocalKeystore; use sc_keystore::LocalKeystore;
use sc_service::{error::Error as ServiceError, Configuration, PartialComponents, TaskManager}; use sc_service::{error::Error as ServiceError, Configuration, PartialComponents, TaskManager};
use sc_telemetry::{Telemetry, TelemetryWorker}; use sc_telemetry::{Telemetry, TelemetryWorker};
use sp_consensus::SlotData;
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use sp_core::H256; use sp_core::H256;
use sp_runtime::traits::BlakeTwo256; use sp_runtime::traits::BlakeTwo256;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
...@@ -41,7 +38,9 @@ type FullClient<RuntimeApi, Executor> = ...@@ -41,7 +38,9 @@ type FullClient<RuntimeApi, Executor> =
type FullBackend = sc_service::TFullBackend<Block>; type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>; type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
#[cfg(feature = "gdev")]
pub struct GDevExecutor; pub struct GDevExecutor;
#[cfg(feature = "gdev")]
impl sc_executor::NativeExecutionDispatch for GDevExecutor { impl sc_executor::NativeExecutionDispatch for GDevExecutor {
/// Only enable the benchmarking host functions when we actually want to benchmark. /// Only enable the benchmarking host functions when we actually want to benchmark.
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
...@@ -59,7 +58,9 @@ impl sc_executor::NativeExecutionDispatch for GDevExecutor { ...@@ -59,7 +58,9 @@ impl sc_executor::NativeExecutionDispatch for GDevExecutor {
} }
} }
#[cfg(feature = "gtest")]
pub struct GTestExecutor; pub struct GTestExecutor;
#[cfg(feature = "gtest")]
impl sc_executor::NativeExecutionDispatch for GTestExecutor { impl sc_executor::NativeExecutionDispatch for GTestExecutor {
/// Only enable the benchmarking host functions when we actually want to benchmark. /// Only enable the benchmarking host functions when we actually want to benchmark.
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
...@@ -77,7 +78,9 @@ impl sc_executor::NativeExecutionDispatch for GTestExecutor { ...@@ -77,7 +78,9 @@ impl sc_executor::NativeExecutionDispatch for GTestExecutor {
} }
} }
#[cfg(feature = "g1")]
pub struct G1Executor; pub struct G1Executor;
#[cfg(feature = "g1")]
impl sc_executor::NativeExecutionDispatch for G1Executor { impl sc_executor::NativeExecutionDispatch for G1Executor {
/// Only enable the benchmarking host functions when we actually want to benchmark. /// Only enable the benchmarking host functions when we actually want to benchmark.
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
...@@ -95,30 +98,32 @@ impl sc_executor::NativeExecutionDispatch for G1Executor { ...@@ -95,30 +98,32 @@ impl sc_executor::NativeExecutionDispatch for G1Executor {
} }
} }
/// Can be called for a `Configuration` to check if it is a configuration for pub enum RuntimeType {
/// a particular network. G1,
pub trait IdentifyVariant { GDev,
/// Returns `true` if this is a configuration for the `main` network. GTest,
fn is_main(&self) -> bool;
/// Returns `true` if this is a configuration for the `test` network.
fn is_test(&self) -> bool;
/// Returns `true` if this is a configuration for a dev network.
fn is_dev(&self) -> bool;
} }
impl IdentifyVariant for Box<dyn sc_chain_spec::ChainSpec> { /// Can be called for a `Configuration` to check if it is a configuration for
fn is_main(&self) -> bool { /// a particular runtime type.
self.id().starts_with("g1") pub trait IdentifyRuntimeType {
} /// Returns the runtime type
fn runtime_type(&self) -> RuntimeType;
fn is_test(&self) -> bool { }
self.id().starts_with("gtest")
}
fn is_dev(&self) -> bool { impl IdentifyRuntimeType for Box<dyn sc_chain_spec::ChainSpec> {
self.id().starts_with("dev") || self.id().starts_with("gdev") fn runtime_type(&self) -> RuntimeType {
if self.id().starts_with("g1") {
RuntimeType::G1
} else if self.id().starts_with("gdem") {
RuntimeType::GTest
} else if self.id().starts_with("dev") || self.id().starts_with("gdev") {
RuntimeType::GDev
} else if self.id().starts_with("gt") {
RuntimeType::GTest
} else {
panic!("unknown runtime")
}
} }
} }
...@@ -135,53 +140,66 @@ pub fn new_chain_ops( ...@@ -135,53 +140,66 @@ pub fn new_chain_ops(
), ),
ServiceError, ServiceError,
> { > {
if config.chain_spec.is_main() { match config.chain_spec.runtime_type() {
let PartialComponents { #[cfg(feature = "g1")]
client, RuntimeType::G1::G1 => {
backend, let PartialComponents {
import_queue, client,
task_manager, backend,
.. import_queue,
} = new_partial::<g1_runtime::RuntimeApi, G1Executor>(config, false)?; task_manager,
Ok(( ..
Arc::new(Client::G1(client)), } = new_partial::<g1_runtime::RuntimeApi, G1Executor>(config, false)?;
backend, Ok((
import_queue, Arc::new(Client::G1(client)),
task_manager, backend,
)) import_queue,
} else if config.chain_spec.is_test() { task_manager,
let PartialComponents { ))
client, }
backend, #[cfg(feature = "gtest")]
import_queue, RuntimeType::GTest => {
task_manager, let PartialComponents {
.. client,
} = new_partial::<gtest_runtime::RuntimeApi, GTestExecutor>(config, false)?; backend,
Ok(( import_queue,
Arc::new(Client::GTest(client)), task_manager,
backend, ..
import_queue, } = new_partial::<gtest_runtime::RuntimeApi, GTestExecutor>(config, false)?;
task_manager, Ok((
)) Arc::new(Client::GTest(client)),
} else if config.chain_spec.is_dev() { backend,
let PartialComponents { import_queue,
client, task_manager,
backend, ))
import_queue, }
task_manager, #[cfg(feature = "gdev")]
.. RuntimeType::GDev => {
} = new_partial::<gdev_runtime::RuntimeApi, GDevExecutor>(config, true)?; let PartialComponents {
Ok(( client,
Arc::new(Client::GDev(client)), backend,
backend, import_queue,
import_queue, task_manager,
task_manager, ..
)) } = new_partial::<gdev_runtime::RuntimeApi, GDevExecutor>(config, true)?;
} else { Ok((
unreachable!() Arc::new(Client::GDev(client)),
backend,
import_queue,
task_manager,
))
}
_ => panic!("unknown runtime"),
} }
} }
type FullGrandpaBlockImport<RuntimeApi, Executor> = sc_finality_grandpa::GrandpaBlockImport<
FullBackend,
Block,
FullClient<RuntimeApi, Executor>,
FullSelectChain,
>;
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub fn new_partial<RuntimeApi, Executor>( pub fn new_partial<RuntimeApi, Executor>(
config: &Configuration, config: &Configuration,
...@@ -194,12 +212,15 @@ pub fn new_partial<RuntimeApi, Executor>( ...@@ -194,12 +212,15 @@ pub fn new_partial<RuntimeApi, Executor>(
sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, Executor>>, sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, Executor>>,
sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, Executor>>, sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, Executor>>,
( (
sc_finality_grandpa::GrandpaBlockImport< Option<(
FullBackend, babe::BabeBlockImport<
Block, Block,
FullClient<RuntimeApi, Executor>, FullClient<RuntimeApi, Executor>,
FullSelectChain, FullGrandpaBlockImport<RuntimeApi, Executor>,
>, >,
babe::BabeLink<Block>,
)>,
FullGrandpaBlockImport<RuntimeApi, Executor>,
sc_finality_grandpa::LinkHalf<Block, FullClient<RuntimeApi, Executor>, FullSelectChain>, sc_finality_grandpa::LinkHalf<Block, FullClient<RuntimeApi, Executor>, FullSelectChain>,
Option<Telemetry>, Option<Telemetry>,
), ),
...@@ -271,37 +292,47 @@ where ...@@ -271,37 +292,47 @@ where
telemetry.as_ref().map(|x| x.handle()), telemetry.as_ref().map(|x| x.handle()),
)?; )?;
let import_queue = if consensus_manual { let justification_import = grandpa_block_import.clone();
sc_consensus_manual_seal::import_queue(
Box::new(grandpa_block_import.clone()), let (babe_setup_opt, import_queue) = if consensus_manual {
&task_manager.spawn_essential_handle(), (
config.prometheus_registry(), None,
sc_consensus_manual_seal::import_queue(
Box::new(grandpa_block_import.clone()),
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
),
) )
} else { } else {
let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); let babe_config = babe::Config::get(&*client)?;
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams { let (babe_block_import, babe_link) =
block_import: grandpa_block_import.clone(), babe::block_import(babe_config, grandpa_block_import.clone(), client.clone())?;
justification_import: Some(Box::new(grandpa_block_import.clone())), let slot_duration = babe_link.config().slot_duration();
client: client.clone(), (
create_inherent_data_providers: move |_, ()| async move { Some((babe_block_import.clone(), babe_link.clone())),
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); babe::import_queue(
babe_link,
let slot = babe_block_import,
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( Some(Box::new(justification_import)),
client.clone(),
select_chain.clone(),
move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp, *timestamp,
slot_duration, slot_duration,
); );
Ok((timestamp, slot)) Ok((timestamp, slot))
}, },
spawner: &task_manager.spawn_essential_handle(), &task_manager.spawn_essential_handle(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new( config.prometheus_registry(),
client.executor().clone(), sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
), telemetry.as_ref().map(|x| x.handle()),
registry: config.prometheus_registry(), )?,
check_for_equivocation: Default::default(), )
telemetry: telemetry.as_ref().map(|x| x.handle()),
})?
}; };
Ok(sc_service::PartialComponents { Ok(sc_service::PartialComponents {
...@@ -312,7 +343,12 @@ where ...@@ -312,7 +343,12 @@ where
keystore_container, keystore_container,
select_chain, select_chain,
transaction_pool, transaction_pool,
other: (grandpa_block_import, grandpa_link, telemetry), other: (
babe_setup_opt,
grandpa_block_import,
grandpa_link,
telemetry,
),
}) })
} }
...@@ -345,7 +381,7 @@ where ...@@ -345,7 +381,7 @@ where
mut keystore_container, mut keystore_container,
select_chain, select_chain,
transaction_pool, transaction_pool,
other: (block_import, grandpa_link, mut telemetry), other: (babe_setup_opt, block_import, grandpa_link, mut telemetry),
} = new_partial::<RuntimeApi, Executor>(&config, sealing_opt.is_some())?; } = new_partial::<RuntimeApi, Executor>(&config, sealing_opt.is_some())?;
if let Some(url) = &config.keystore_remote { if let Some(url) = &config.keystore_remote {
...@@ -456,61 +492,81 @@ where ...@@ -456,61 +492,81 @@ where
create_inherent_data_providers: move |_, ()| async move { Ok(()) }, create_inherent_data_providers: move |_, ()| async move { Ok(()) },
}), }),
); );
} else { } else if let Some((babe_block_import, babe_link)) = babe_setup_opt {
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
let raw_slot_duration = slot_duration.slot_duration();
let can_author_with = let can_author_with =
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>( let client_clone = client.clone();
StartAuraParams { let slot_duration = babe_link.config().slot_duration();
slot_duration, let babe_config = babe::BabeParams {
client: client.clone(), keystore: keystore_container.sync_keystore(),
select_chain, client: client.clone(),
block_import, select_chain,
proposer_factory, block_import: babe_block_import,
create_inherent_data_providers: move |_, ()| async move { env: proposer_factory,
sync_oracle: network.clone(),
justification_sync_link: network.clone(),
create_inherent_data_providers: move |parent, ()| {
let client_clone = client_clone.clone();
async move {
let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider(
&*client_clone,
parent,
)?;
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp, *timestamp,
raw_slot_duration, slot_duration,
); );
Ok((timestamp, slot)) Ok((timestamp, slot, uncles))
}, }
force_authoring,
backoff_authoring_blocks,
keystore: keystore_container.sync_keystore(),
can_author_with,
sync_oracle: network.clone(),
justification_sync_link: network.clone(),
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
}, },
)?; force_authoring,
backoff_authoring_blocks,
babe_link,
can_author_with,
block_proposal_slot_portion: babe::SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
let babe = babe::start_babe(babe_config)?;
// the AURA authoring task is considered essential, i.e. if it // the BABE authoring task is considered essential, i.e. if it
// fails we take down the service with it. // fails we take down the service with it.
task_manager.spawn_essential_handle().spawn_blocking( task_manager.spawn_essential_handle().spawn_blocking(
"aura", "babe",
Some("block-authoring"), Some("block-authoring"),
aura, babe,
); );
} else {
panic!("We must have babe or manual seal")
} }
} }
let rpc_extensions_builder = { let rpc_extensions_builder = {
let client = client.clone(); let client = client.clone();
//let keystore = keystore_container.sync_keystore();
let pool = transaction_pool.clone(); let pool = transaction_pool.clone();
//let select_chain = select_chain.clone();
//let chain_spec = config.chain_spec.cloned_box();
Box::new(move |deny_unsafe, _| { Box::new(move |deny_unsafe, _| {
let deps = crate::rpc::FullDeps { let deps = crate::rpc::FullDeps {
client: client.clone(), client: client.clone(),
pool: pool.clone(), pool: pool.clone(),
//select_chain: select_chain.clone(),
//chain_spec: chain_spec.cloned_box(),
deny_unsafe, deny_unsafe,
/*babe: crate::rpc::BabeDeps {
babe_config: babe_config.clone(),
shared_epoch_changes: shared_epoch_changes.clone(),
keystore: keystore.clone(),
},*/
command_sink_opt: command_sink_opt.clone(), command_sink_opt: command_sink_opt.clone(),
}; };
......
...@@ -29,17 +29,22 @@ use std::sync::Arc; ...@@ -29,17 +29,22 @@ use std::sync::Arc;
/// A client instance. /// A client instance.
#[derive(Clone)] #[derive(Clone)]
pub enum Client { pub enum Client {
#[cfg(feature = "g1")]
G1(Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>), G1(Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>),
#[cfg(feature = "gtest")]
GTest(Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>), GTest(Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>),
#[cfg(feature = "gdev")]
GDev(Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>), GDev(Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>),
} }
#[cfg(feature = "g1")]
impl From<Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>> for Client { impl From<Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>> for Client {
fn from(client: Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>) -> Self { fn from(client: Arc<super::FullClient<g1_runtime::RuntimeApi, super::G1Executor>>) -> Self {
Self::G1(client) Self::G1(client)
} }
} }
#[cfg(feature = "gtest")]
impl From<Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>> for Client { impl From<Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>> for Client {
fn from( fn from(
client: Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>, client: Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>>,
...@@ -48,6 +53,7 @@ impl From<Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor> ...@@ -48,6 +53,7 @@ impl From<Arc<super::FullClient<gtest_runtime::RuntimeApi, super::GTestExecutor>
} }
} }
#[cfg(feature = "gdev")]
impl From<Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>> for Client { impl From<Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>> for Client {
fn from(client: Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>) -> Self { fn from(client: Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>) -> Self {
Self::GDev(client) Self::GDev(client)
...@@ -57,8 +63,11 @@ impl From<Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>> ...@@ -57,8 +63,11 @@ impl From<Arc<super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor>>>
macro_rules! match_client { macro_rules! match_client {
($self:ident, $method:ident($($param:ident),*)) => { ($self:ident, $method:ident($($param:ident),*)) => {
match $self { match $self {
#[cfg(feature = "g1")]
Self::G1(client) => client.$method($($param),*), Self::G1(client) => client.$method($($param),*),
#[cfg(feature = "gtest")]
Self::GTest(client) => client.$method($($param),*), Self::GTest(client) => client.$method($($param),*),
#[cfg(feature = "gdev")]
Self::GDev(client) => client.$method($($param),*), Self::GDev(client) => client.$method($($param),*),
} }
}; };
...@@ -233,32 +242,34 @@ impl sp_blockchain::HeaderBackend<Block> for Client { ...@@ -233,32 +242,34 @@ impl sp_blockchain::HeaderBackend<Block> for Client {
/// This trait has no methods or associated type. It is a concise marker for all the trait bounds /// This trait has no methods or associated type. It is a concise marker for all the trait bounds
/// that it contains. /// that it contains.
pub trait RuntimeApiCollection: pub trait RuntimeApiCollection:
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> pallet_grandpa::fg_primitives::GrandpaApi<Block>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_api::ApiExt<Block> + sp_api::ApiExt<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
+ sp_block_builder::BlockBuilder<Block> + sp_block_builder::BlockBuilder<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ pallet_grandpa::fg_primitives::GrandpaApi<Block>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_api::Metadata<Block> + sp_api::Metadata<Block>
+ sp_consensus_aura::AuraApi<Block, sp_consensus_aura::sr25519::AuthorityId> + sp_consensus_babe::BabeApi<Block>
+ sp_offchain::OffchainWorkerApi<Block> + sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block> + sp_session::SessionKeys<Block>
+ sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
where where
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>, <Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{ {
} }
impl<Api> RuntimeApiCollection for Api impl<Api> RuntimeApiCollection for Api
where where
Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> Api: pallet_grandpa::fg_primitives::GrandpaApi<Block>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_api::ApiExt<Block> + sp_api::ApiExt<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
+ sp_block_builder::BlockBuilder<Block> + sp_block_builder::BlockBuilder<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ pallet_grandpa::fg_primitives::GrandpaApi<Block>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_api::Metadata<Block> + sp_api::Metadata<Block>
+ sp_consensus_aura::AuraApi<Block, sp_consensus_aura::sr25519::AuthorityId> + sp_consensus_babe::BabeApi<Block>
+ sp_offchain::OffchainWorkerApi<Block> + sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block>, + sp_session::SessionKeys<Block>
+ sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>, <Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{ {
} }
...@@ -6,7 +6,7 @@ homepage = 'https://substrate.dev' ...@@ -6,7 +6,7 @@ homepage = 'https://substrate.dev'
license = 'AGPL-3.0' license = 'AGPL-3.0'
name = 'pallet-certification' name = 'pallet-certification'
readme = 'README.md' readme = 'README.md'
repository = 'https://git.duniter.org/nodes/rust/duniter-substrate' repository = 'https://git.duniter.org/nodes/rust/duniter-v2s'
version = '3.0.0' version = '3.0.0'
[features] [features]
......
...@@ -30,7 +30,7 @@ pub use types::*; ...@@ -30,7 +30,7 @@ pub use types::*;
use crate::traits::*; use crate::traits::*;
use codec::Codec; use codec::Codec;
use frame_support::traits::{Instance, StorageVersion}; use frame_support::traits::StorageVersion;
use sp_runtime::traits::AtLeast32BitUnsigned; use sp_runtime::traits::AtLeast32BitUnsigned;
use sp_std::{fmt::Debug, vec::Vec}; use sp_std::{fmt::Debug, vec::Vec};
...@@ -39,7 +39,7 @@ pub mod pallet { ...@@ -39,7 +39,7 @@ pub mod pallet {
use super::*; use super::*;
use frame_support::pallet_prelude::*; use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*; use frame_system::pallet_prelude::*;
use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use sp_std::collections::btree_map::BTreeMap;
/// The current storage version. /// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
...@@ -85,10 +85,11 @@ pub mod pallet { ...@@ -85,10 +85,11 @@ pub mod pallet {
type ValidityPeriod: Get<Self::BlockNumber>; type ValidityPeriod: Get<Self::BlockNumber>;
} }
// GENESIS STUFF //
#[pallet::genesis_config] #[pallet::genesis_config]
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> { pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
pub certs_by_issuer: BTreeMap<T::IdtyIndex, BTreeSet<T::IdtyIndex>>, pub certs_by_issuer: BTreeMap<T::IdtyIndex, BTreeMap<T::IdtyIndex, T::BlockNumber>>,
pub phantom: PhantomData<I>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
...@@ -96,7 +97,6 @@ pub mod pallet { ...@@ -96,7 +97,6 @@ pub mod pallet {
fn default() -> Self { fn default() -> Self {
Self { Self {
certs_by_issuer: Default::default(), certs_by_issuer: Default::default(),
phantom: Default::default(),
} }
} }
} }
...@@ -109,7 +109,7 @@ pub mod pallet { ...@@ -109,7 +109,7 @@ pub mod pallet {
let mut certs_by_receiver = BTreeMap::<T::IdtyIndex, Vec<T::IdtyIndex>>::new(); let mut certs_by_receiver = BTreeMap::<T::IdtyIndex, Vec<T::IdtyIndex>>::new();
for (issuer, receivers) in &self.certs_by_issuer { for (issuer, receivers) in &self.certs_by_issuer {
assert!( assert!(
!receivers.contains(issuer), !receivers.contains_key(issuer),
"Identity cannot certify it-self." "Identity cannot certify it-self."
); );
assert!( assert!(
...@@ -122,11 +122,11 @@ pub mod pallet { ...@@ -122,11 +122,11 @@ pub mod pallet {
*issuer, *issuer,
IdtyCertMeta { IdtyCertMeta {
issued_count: receivers.len() as u8, issued_count: receivers.len() as u8,
next_issuable_on: T::CertPeriod::get(), next_issuable_on: sp_runtime::traits::Zero::zero(),
received_count: 0, received_count: 0,
}, },
); );
for receiver in receivers { for receiver in receivers.keys() {
certs_by_receiver certs_by_receiver
.entry(*receiver) .entry(*receiver)
.or_default() .or_default()
...@@ -142,26 +142,47 @@ pub mod pallet { ...@@ -142,26 +142,47 @@ pub mod pallet {
issuers.sort(); issuers.sort();
<StorageCertsByReceiver<T, I>>::insert(receiver, issuers); <StorageCertsByReceiver<T, I>>::insert(receiver, issuers);
} }
// Write StorageIdtyCertMeta // Write StorageCertsByIssuer
for (issuer, cert_meta) in cert_meta_by_issuer { let mut certs_removable_on =
<StorageIdtyCertMeta<T, I>>::insert(issuer, cert_meta); BTreeMap::<T::BlockNumber, Vec<(T::IdtyIndex, T::IdtyIndex)>>::new();
}
// Write StorageCertsByIssuer && StorageCertsRemovableOn
let mut all_couples = Vec::new();
for (issuer, receivers) in &self.certs_by_issuer { for (issuer, receivers) in &self.certs_by_issuer {
for receiver in receivers { for (receiver, removable_on) in receivers {
all_couples.push((*issuer, *receiver)); certs_removable_on
.entry(*removable_on)
.or_default()
.push((*issuer, *receiver));
use sp_runtime::traits::Saturating as _;
let issuer_next_issuable_on = removable_on
.saturating_add(T::CertPeriod::get())
.saturating_sub(T::ValidityPeriod::get());
if let Some(cert_meta) = cert_meta_by_issuer.get_mut(issuer) {
if cert_meta.next_issuable_on < issuer_next_issuable_on {
cert_meta.next_issuable_on = issuer_next_issuable_on;
}
}
let renewable_on = removable_on.saturating_sub(
T::ValidityPeriod::get().saturating_sub(T::CertRenewablePeriod::get()),
);
<StorageCertsByIssuer<T, I>>::insert( <StorageCertsByIssuer<T, I>>::insert(
issuer, issuer,
receiver, receiver,
CertValue { CertValue {
renewable_on: T::CertRenewablePeriod::get(), renewable_on,
removable_on: T::ValidityPeriod::get(), removable_on: *removable_on,
}, },
); );
} }
} }
<StorageCertsRemovableOn<T, I>>::insert(T::ValidityPeriod::get(), all_couples); // Write StorageIdtyCertMeta
for (issuer, cert_meta) in cert_meta_by_issuer {
<StorageIdtyCertMeta<T, I>>::insert(issuer, cert_meta);
}
// Write storage StorageCertsRemovableOn
for (removable_on, certs) in certs_removable_on {
<StorageCertsRemovableOn<T, I>>::insert(removable_on, certs);
}
} }
} }
...@@ -371,19 +392,19 @@ pub mod pallet { ...@@ -371,19 +392,19 @@ pub mod pallet {
Self::remove_cert_inner(issuer, receiver, None); Self::remove_cert_inner(issuer, receiver, None);
Ok(().into()) Ok(().into())
} }
}
// PUBLIC FUNCTIONS //
impl<T: Config<I>, I: Instance> Pallet<T, I> { #[pallet::weight(0)]
pub fn on_idty_removed(idty_index: T::IdtyIndex) -> Weight { pub fn remove_all_certs_received_by(
let mut total_weight: Weight = 0; origin: OriginFor<T>,
idty_index: T::IdtyIndex,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
if let Ok(issuers) = <StorageCertsByReceiver<T, I>>::try_get(idty_index) { if let Ok(issuers) = <StorageCertsByReceiver<T, I>>::try_get(idty_index) {
for issuer in issuers { for issuer in issuers {
total_weight += Self::remove_cert_inner(issuer, idty_index, None); Self::remove_cert_inner(issuer, idty_index, None);
} }
} }
total_weight Ok(().into())
} }
} }
...@@ -472,3 +493,16 @@ impl<T: Config<I>, I: 'static> IsIdtyAllowedToCreateCert<T::IdtyIndex> for Palle ...@@ -472,3 +493,16 @@ impl<T: Config<I>, I: 'static> IsIdtyAllowedToCreateCert<T::IdtyIndex> for Palle
} }
} }
} }
impl<T: Config<I>, I: 'static> SetNextIssuableOn<T::BlockNumber, T::IdtyIndex> for Pallet<T, I> {
fn set_next_issuable_on(
idty_index: T::IdtyIndex,
next_issuable_on: T::BlockNumber,
) -> frame_support::pallet_prelude::Weight {
<StorageIdtyCertMeta<T, I>>::mutate_exists(idty_index, |cert_meta_opt| {
let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default());
cert_meta.next_issuable_on = next_issuable_on;
});
0
}
}
...@@ -14,18 +14,18 @@ ...@@ -14,18 +14,18 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use crate::mock::Event as RuntimeEvent;
use crate::mock::*; use crate::mock::*;
use crate::Error; use crate::{Error, Event};
use frame_support::assert_ok; use frame_support::assert_ok;
//use frame_system::{EventRecord, Phase}; //use frame_system::{EventRecord, Phase};
use maplit::{btreemap, btreeset}; use maplit::btreemap;
use sp_std::collections::btree_map::BTreeMap; use sp_std::collections::btree_map::BTreeMap;
#[test] #[test]
fn test_must_receive_cert_before_can_issue() { fn test_must_receive_cert_before_can_issue() {
new_test_ext(DefaultCertificationConfig { new_test_ext(DefaultCertificationConfig {
certs_by_issuer: BTreeMap::new(), certs_by_issuer: BTreeMap::new(),
phantom: core::marker::PhantomData,
}) })
.execute_with(|| { .execute_with(|| {
assert_eq!( assert_eq!(
...@@ -35,11 +35,83 @@ fn test_must_receive_cert_before_can_issue() { ...@@ -35,11 +35,83 @@ fn test_must_receive_cert_before_can_issue() {
}); });
} }
#[test]
fn test_genesis_build() {
new_test_ext(DefaultCertificationConfig {
certs_by_issuer: btreemap![
0 => btreemap![
1 => 10,
2 => 5,
],
1 => btreemap![
0 => 7,
2 => 4,
],
2 => btreemap![
0 => 9,
1 => 3,
],
],
})
.execute_with(|| {
run_to_block(1);
// Verify state of idty 0
assert_eq!(
DefaultCertification::idty_cert_meta(0),
Some(crate::IdtyCertMeta {
issued_count: 2,
next_issuable_on: 2,
received_count: 2,
})
);
// Verify state of idty 1
assert_eq!(
DefaultCertification::idty_cert_meta(1),
Some(crate::IdtyCertMeta {
issued_count: 2,
next_issuable_on: 0,
received_count: 2,
})
);
// Verify state of idty 2
assert_eq!(
DefaultCertification::idty_cert_meta(2),
Some(crate::IdtyCertMeta {
issued_count: 2,
next_issuable_on: 1,
received_count: 2,
})
);
// Cert 2->1 must be removable at block #3
assert_eq!(
DefaultCertification::certs_removable_on(3),
Some(vec![(2, 1)]),
);
// Cert 2->0 cannot be renewed before #5
assert_eq!(
DefaultCertification::add_cert(Origin::root(), 2, 0),
Err(Error::<Test, _>::NotRespectRenewablePeriod.into())
);
run_to_block(3);
// Cert 2->1 must have expired
assert_eq!(
System::events()[0].event,
RuntimeEvent::DefaultCertification(Event::RemovedCert {
issuer: 2,
issuer_issued_count: 1,
receiver: 1,
receiver_received_count: 1,
expiration: true,
},)
);
});
}
#[test] #[test]
fn test_cert_period() { fn test_cert_period() {
new_test_ext(DefaultCertificationConfig { new_test_ext(DefaultCertificationConfig {
certs_by_issuer: btreemap![0 => btreeset![1]], certs_by_issuer: btreemap![0 => btreemap![1 => 10]],
phantom: core::marker::PhantomData,
}) })
.execute_with(|| { .execute_with(|| {
assert_eq!( assert_eq!(
...@@ -61,8 +133,7 @@ fn test_cert_period() { ...@@ -61,8 +133,7 @@ fn test_cert_period() {
#[test] #[test]
fn test_renewable_period() { fn test_renewable_period() {
new_test_ext(DefaultCertificationConfig { new_test_ext(DefaultCertificationConfig {
certs_by_issuer: btreemap![0 => btreeset![1]], certs_by_issuer: btreemap![0 => btreemap![1 => 10]],
phantom: core::marker::PhantomData,
}) })
.execute_with(|| { .execute_with(|| {
run_to_block(CertPeriod::get()); run_to_block(CertPeriod::get());
......
...@@ -57,3 +57,10 @@ impl<IdtyIndex> OnRemovedCert<IdtyIndex> for () { ...@@ -57,3 +57,10 @@ impl<IdtyIndex> OnRemovedCert<IdtyIndex> for () {
0 0
} }
} }
pub trait SetNextIssuableOn<BlockNumber, IdtyIndex> {
fn set_next_issuable_on(
idty_index: IdtyIndex,
next_issuable_on: BlockNumber,
) -> frame_support::dispatch::Weight;
}
...@@ -6,7 +6,7 @@ homepage = 'https://substrate.dev' ...@@ -6,7 +6,7 @@ homepage = 'https://substrate.dev'
license = 'AGPL-3.0' license = 'AGPL-3.0'
name = 'pallet-identity' name = 'pallet-identity'
readme = 'README.md' readme = 'README.md'
repository = 'https://git.duniter.org/nodes/rust/duniter-substrate' repository = 'https://git.duniter.org/nodes/rust/duniter-v2s'
version = '3.0.0' version = '3.0.0'
[features] [features]
...@@ -19,12 +19,14 @@ std = [ ...@@ -19,12 +19,14 @@ std = [
'frame-benchmarking/std', 'frame-benchmarking/std',
'serde', 'serde',
'sp-core/std', 'sp-core/std',
'sp-membership/std',
'sp-runtime/std', 'sp-runtime/std',
'sp-std/std', 'sp-std/std',
] ]
try-runtime = ['frame-support/try-runtime'] try-runtime = ['frame-support/try-runtime']
[dependencies] [dependencies]
sp-membership = { path = "../../primitives/membership", default-features = false }
# substrate # substrate
scale-info = { version = "1.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] }
...@@ -81,6 +83,5 @@ version = '1.0.119' ...@@ -81,6 +83,5 @@ version = '1.0.119'
### DEV ### ### DEV ###
[dev-dependencies.sp-io] [dev-dependencies.sp-io]
default-features = false
git = 'https://github.com/librelois/substrate.git' git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01' branch = 'duniter-monthly-2022-01'
This diff is collapsed.
...@@ -114,6 +114,7 @@ impl system::Config for Test { ...@@ -114,6 +114,7 @@ impl system::Config for Test {
parameter_types! { parameter_types! {
pub const ConfirmPeriod: u64 = 2; pub const ConfirmPeriod: u64 = 2;
pub const IdtyCreationPeriod: u64 = 3;
pub const MaxInactivityPeriod: u64 = 5; pub const MaxInactivityPeriod: u64 = 5;
pub const MaxNoRightPeriod: u64 = 4; pub const MaxNoRightPeriod: u64 = 4;
pub const RenewablePeriod: u64 = 3; pub const RenewablePeriod: u64 = 3;
...@@ -123,7 +124,7 @@ parameter_types! { ...@@ -123,7 +124,7 @@ parameter_types! {
pub struct IdtyNameValidatorTestImpl; pub struct IdtyNameValidatorTestImpl;
impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl { impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl {
fn validate(idty_name: &pallet_identity::IdtyName) -> bool { fn validate(idty_name: &pallet_identity::IdtyName) -> bool {
idty_name.0.len() == 1 idty_name.0.len() < 16
} }
} }
...@@ -133,6 +134,7 @@ impl pallet_identity::Config for Test { ...@@ -133,6 +134,7 @@ impl pallet_identity::Config for Test {
type AddRightOrigin = system::EnsureRoot<AccountId>; type AddRightOrigin = system::EnsureRoot<AccountId>;
type DelRightOrigin = system::EnsureRoot<AccountId>; type DelRightOrigin = system::EnsureRoot<AccountId>;
type EnsureIdtyCallAllowed = (); type EnsureIdtyCallAllowed = ();
type IdtyCreationPeriod = IdtyCreationPeriod;
type IdtyData = (); type IdtyData = ();
type IdtyDataProvider = (); type IdtyDataProvider = ();
type IdtyNameValidator = IdtyNameValidatorTestImpl; type IdtyNameValidator = IdtyNameValidatorTestImpl;
...@@ -141,10 +143,8 @@ impl pallet_identity::Config for Test { ...@@ -141,10 +143,8 @@ impl pallet_identity::Config for Test {
type IdtyRight = IdtyRight; type IdtyRight = IdtyRight;
type OnIdtyChange = (); type OnIdtyChange = ();
type OnRightKeyChange = (); type OnRightKeyChange = ();
type MaxInactivityPeriod = MaxInactivityPeriod;
type MaxNoRightPeriod = MaxNoRightPeriod; type MaxNoRightPeriod = MaxNoRightPeriod;
type RenewablePeriod = RenewablePeriod; type Membership = ();
type ValidationPeriod = ValidationPeriod;
} }
// Build genesis storage according to the mock runtime. // Build genesis storage according to the mock runtime.
...@@ -162,6 +162,7 @@ pub fn run_to_block(n: u64) { ...@@ -162,6 +162,7 @@ pub fn run_to_block(n: u64) {
while System::block_number() < n { while System::block_number() < n {
Identity::on_finalize(System::block_number()); Identity::on_finalize(System::block_number());
System::on_finalize(System::block_number()); System::on_finalize(System::block_number());
System::reset_events();
System::set_block_number(System::block_number() + 1); System::set_block_number(System::block_number() + 1);
System::on_initialize(System::block_number()); System::on_initialize(System::block_number());
Identity::on_initialize(System::block_number()); Identity::on_initialize(System::block_number());
......
...@@ -16,43 +16,181 @@ ...@@ -16,43 +16,181 @@
use crate::mock::IdtyRight as Right; use crate::mock::IdtyRight as Right;
use crate::mock::*; use crate::mock::*;
use crate::{Error, IdtyName}; use crate::{Error, IdtyName, IdtyValue};
use frame_support::assert_err; use frame_support::assert_err;
use frame_support::assert_ok; use frame_support::assert_ok;
use frame_system::{EventRecord, Phase}; use frame_system::{EventRecord, Phase};
type IdtyVal = IdtyValue<u64, u64, (), Right>;
fn alice() -> IdtyVal {
IdtyVal {
data: (),
owner_key: 1,
name: IdtyName::from("Alice"),
next_creatable_identity_on: 0,
removable_on: 0,
rights: vec![(Right::Right1, None)],
status: crate::IdtyStatus::Validated,
}
}
fn bob() -> IdtyVal {
IdtyVal {
data: (),
owner_key: 2,
name: IdtyName::from("Bob"),
next_creatable_identity_on: 0,
removable_on: 0,
rights: vec![(Right::Right2, Some(20))],
status: crate::IdtyStatus::Validated,
}
}
#[test] #[test]
fn test_no_identity() { fn test_no_identity() {
let identities = Vec::with_capacity(0); new_test_ext(IdentityConfig {
new_test_ext(IdentityConfig { identities }).execute_with(|| { identities: Vec::with_capacity(0),
})
.execute_with(|| {
assert_eq!(Identity::identities_count(), 0); assert_eq!(Identity::identities_count(), 0);
}); });
} }
#[test]
fn test_creator_not_exist() {
new_test_ext(IdentityConfig {
identities: Vec::with_capacity(0),
})
.execute_with(|| {
assert_eq!(
Identity::create_identity(Origin::signed(1), 1, IdtyName::from("bob"), 2),
Err(Error::<Test>::CreatorNotExist.into())
);
});
}
#[test]
fn test_creator_not_have_right_to_create_identity() {
new_test_ext(IdentityConfig {
identities: vec![bob()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Bob not have right to create identities
assert_eq!(
Identity::create_identity(Origin::signed(2), 1, IdtyName::from("Charlie"), 3),
Err(Error::<Test>::CreatorNotHaveRightToCreateIdty.into())
);
})
}
#[test]
fn test_creator_not_owner() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Someone try to create an identity pretending to be Alice
assert_eq!(
Identity::create_identity(Origin::signed(2), 1, IdtyName::from("Charlie"), 3),
Err(Error::<Test>::RequireToBeOwner.into())
);
})
}
#[test]
fn test_create_identity_ok() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Alice should be able te create an identity
assert_ok!(Identity::create_identity(
Origin::signed(1),
1,
IdtyName::from("bob"),
2
));
let events = System::events();
assert_eq!(events.len(), 1);
assert_eq!(
events[0],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("bob"), 2)),
topics: vec![],
}
);
});
}
#[test]
fn test_idty_creation_period() {
new_test_ext(IdentityConfig {
identities: vec![alice()],
})
.execute_with(|| {
// We need to initialize at least one block before any call
run_to_block(1);
// Alice should be able te create an identity
assert_ok!(Identity::create_identity(
Origin::signed(1),
1,
IdtyName::from("bob"),
2
));
let events = System::events();
assert_eq!(events.len(), 1);
assert_eq!(
events[0],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("bob"), 2)),
topics: vec![],
}
);
assert_eq!(Identity::identity(1).unwrap().next_creatable_identity_on, 4);
// Alice cannot create a new identity before block #4
run_to_block(2);
assert_eq!(
Identity::create_identity(Origin::signed(1), 1, IdtyName::from("Charlie"), 3),
Err(Error::<Test>::NotRespectIdtyCreationPeriod.into())
);
// Alice should be able te create a second identity after block #4
run_to_block(4);
assert_ok!(Identity::create_identity(
Origin::signed(1),
1,
IdtyName::from("Charlie"),
3
));
let events = System::events();
assert_eq!(events.len(), 1);
assert_eq!(
events[0],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("Charlie"), 3)),
topics: vec![],
}
);
});
}
#[test] #[test]
fn test_two_identities() { fn test_two_identities() {
let identities = vec![ let identities = vec![alice(), bob()];
crate::IdtyValue {
name: IdtyName(vec![0]),
expire_on: 5,
owner_key: 1,
removable_on: 0,
renewable_on: 3,
rights: vec![(Right::Right2, Some(10))],
status: crate::IdtyStatus::Validated,
data: (),
},
crate::IdtyValue {
name: IdtyName(vec![1]),
expire_on: 5,
owner_key: 2,
removable_on: 0,
renewable_on: 3,
rights: vec![(Right::Right1, Some(20))],
status: crate::IdtyStatus::Validated,
data: (),
},
];
new_test_ext(IdentityConfig { identities }).execute_with(|| { new_test_ext(IdentityConfig { identities }).execute_with(|| {
// Should have two identities // Should have two identities
...@@ -61,9 +199,15 @@ fn test_two_identities() { ...@@ -61,9 +199,15 @@ fn test_two_identities() {
// We need to initialize at least one block before any call // We need to initialize at least one block before any call
run_to_block(1); run_to_block(1);
// Add right Right1 for IdtyName(vec![0]) // Add right Right1 for Alice
// Should fail because Alice already have this right
assert_err!(
Identity::add_right(Origin::root(), 1, Right::Right1),
Error::<Test>::RightAlreadyAdded
);
// Add right Right2 for alice
// Should succes and trigger the correct event // Should succes and trigger the correct event
assert_ok!(Identity::add_right(Origin::root(), 1, Right::Right1)); assert_ok!(Identity::add_right(Origin::root(), 1, Right::Right2));
let events = System::events(); let events = System::events();
assert_eq!(events.len(), 1); assert_eq!(events.len(), 1);
assert_eq!( assert_eq!(
...@@ -71,39 +215,33 @@ fn test_two_identities() { ...@@ -71,39 +215,33 @@ fn test_two_identities() {
EventRecord { EventRecord {
phase: Phase::Initialization, phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyAcquireRight( event: Event::Identity(crate::Event::IdtyAcquireRight(
IdtyName(vec![0]), IdtyName::from("Alice"),
Right::Right1 Right::Right2
)), )),
topics: vec![], topics: vec![],
} }
); );
// Add right Right2 for IdtyName(vec![0])
// Should fail because IdtyName(vec![0]) already have this right
assert_err!(
Identity::add_right(Origin::root(), 1, Right::Right2),
Error::<Test>::RightAlreadyAdded
);
run_to_block(3); run_to_block(3);
// Delete right Right1 for IdtyName(vec![1]) // Delete right Right2 for Bob
// Should succes and trigger the correct event // Should succes and trigger the correct event
assert_ok!(Identity::del_right(Origin::root(), 2, Right::Right1)); assert_ok!(Identity::del_right(Origin::root(), 2, Right::Right2));
let events = System::events(); let events = System::events();
assert_eq!(events.len(), 2); assert_eq!(events.len(), 1);
assert_eq!( assert_eq!(
events[1], events[0],
EventRecord { EventRecord {
phase: Phase::Initialization, phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyLostRight( event: Event::Identity(crate::Event::IdtyLostRight(
IdtyName(vec![1]), IdtyName::from("Bob"),
Right::Right1 Right::Right2
)), )),
topics: vec![], topics: vec![],
} }
); );
// The IdtyName(vec![1]) identity has no more rights, the inactivity period must start to run // The Bob identity has no more rights, the inactivity period must start to run
let idty2 = Identity::identity(2).expect("idty not found"); let idty2 = Identity::identity(2).expect("idty not found");
assert!(idty2.rights.is_empty()); assert!(idty2.rights.is_empty());
assert_eq!(idty2.removable_on, 7); assert_eq!(idty2.removable_on, 7);
......
...@@ -15,31 +15,17 @@ ...@@ -15,31 +15,17 @@
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use crate::*; use crate::*;
use frame_support::{dispatch::DispatchError, pallet_prelude::*}; use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_runtime::traits::MaybeSerializeDeserialize; use sp_runtime::traits::MaybeSerializeDeserialize;
use sp_std::fmt::Debug; use sp_std::fmt::Debug;
pub trait EnsureIdtyCallAllowed<T: Config> { pub trait EnsureIdtyCallAllowed<T: Config> {
fn can_create_identity( fn can_create_identity(creator: T::IdtyIndex) -> bool;
origin: T::Origin,
creator: T::IdtyIndex,
idty_name: &IdtyName,
idty_owner_key: &T::AccountId,
) -> Result<(), DispatchError>;
} }
impl<T: Config> EnsureIdtyCallAllowed<T> for () { impl<T: Config> EnsureIdtyCallAllowed<T> for () {
fn can_create_identity( fn can_create_identity(_creator: T::IdtyIndex) -> bool {
origin: T::Origin, true
_creator: T::IdtyIndex,
_idty_name: &IdtyName,
_idty_owner_key: &T::AccountId,
) -> Result<(), DispatchError> {
match ensure_root(origin) {
Ok(()) => Ok(()),
Err(_) => Err(DispatchError::BadOrigin),
}
} }
} }
......
...@@ -23,11 +23,39 @@ use scale_info::TypeInfo; ...@@ -23,11 +23,39 @@ use scale_info::TypeInfo;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sp_std::vec::Vec; use sp_std::vec::Vec;
#[cfg_attr(feature = "std", derive(Deserialize, Serialize))] #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)]
#[derive( pub struct IdtyName(pub Vec<u8>);
Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo,
)] impl scale_info::TypeInfo for IdtyName {
pub struct IdtyName(pub sp_std::vec::Vec<u8>); type Identity = str;
fn type_info() -> scale_info::Type {
Self::Identity::type_info()
}
}
#[cfg(feature = "std")]
impl From<&str> for IdtyName {
fn from(s: &str) -> Self {
Self(s.as_bytes().to_vec())
}
}
#[cfg(feature = "std")]
impl serde::Serialize for IdtyName {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
std::str::from_utf8(&self.0)
.map_err(|e| serde::ser::Error::custom(format!("{:?}", e)))?
.serialize(serializer)
}
}
#[cfg(feature = "std")]
impl<'de> serde::Deserialize<'de> for IdtyName {
fn deserialize<D: serde::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
Ok(Self(String::deserialize(de)?.as_bytes().to_vec()))
}
}
#[cfg_attr(feature = "std", derive(Deserialize, Serialize))] #[cfg_attr(feature = "std", derive(Deserialize, Serialize))]
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
...@@ -51,14 +79,13 @@ pub struct IdtyValue< ...@@ -51,14 +79,13 @@ pub struct IdtyValue<
IdtyData: Decode + Encode + TypeInfo, IdtyData: Decode + Encode + TypeInfo,
IdtyRight: Decode + Encode + TypeInfo, IdtyRight: Decode + Encode + TypeInfo,
> { > {
pub name: IdtyName, pub data: IdtyData,
pub expire_on: BlockNumber,
pub owner_key: AccountId, pub owner_key: AccountId,
pub name: IdtyName,
pub next_creatable_identity_on: BlockNumber,
pub removable_on: BlockNumber, pub removable_on: BlockNumber,
pub renewable_on: BlockNumber,
pub rights: Vec<(IdtyRight, Option<AccountId>)>, pub rights: Vec<(IdtyRight, Option<AccountId>)>,
pub status: IdtyStatus, pub status: IdtyStatus,
pub data: IdtyData,
} }
impl<AccountId, BlockNumber, IdtyData, IdtyRight> impl<AccountId, BlockNumber, IdtyData, IdtyRight>
......
[package]
authors = ['librelois <c@elo.tf>']
description = 'FRAME pallet membership.'
edition = '2018'
homepage = 'https://substrate.dev'
license = 'AGPL-3.0'
name = 'pallet-membership'
readme = 'README.md'
repository = 'https://git.duniter.org/nodes/rust/duniter-v2s'
version = '3.0.0'
[features]
default = ['std']
runtime-benchmarks = ['frame-benchmarking']
std = [
'codec/std',
'frame-support/std',
'frame-system/std',
'frame-benchmarking/std',
'serde',
'sp-core/std',
'sp-membership/std',
'sp-runtime/std',
'sp-std/std',
]
try-runtime = ['frame-support/try-runtime']
[dependencies]
sp-membership = { path = "../../primitives/membership", default-features = false }
# substrate
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
[dependencies.codec]
default-features = false
features = ['derive']
package = 'parity-scale-codec'
version = '2.3.1'
[dependencies.frame-benchmarking]
default-features = false
git = 'https://github.com/librelois/substrate.git'
optional = true
branch = 'duniter-monthly-2022-01'
[dependencies.frame-support]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
[dependencies.frame-system]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
[dependencies.serde]
version = "1.0.101"
optional = true
features = ["derive"]
[dependencies.sp-core]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
[dependencies.sp-runtime]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
[dependencies.sp-std]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
### DOC ###
[package.metadata.docs.rs]
targets = ['x86_64-unknown-linux-gnu']
[dev-dependencies.serde]
version = '1.0.119'
### DEV ###
[dev-dependencies.maplit]
version = '1.0.2'
[dev-dependencies.sp-io]
default-features = false
git = 'https://github.com/librelois/substrate.git'
branch = 'duniter-monthly-2022-01'
This diff is collapsed.
// Copyright 2021 Axiom-Team
//
// This file is part of Substrate-Libre-Currency.
//
// Substrate-Libre-Currency is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Substrate-Libre-Currency 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use crate::{self as pallet_membership};
use frame_support::{
parameter_types,
traits::{Everything, OnFinalize, OnInitialize},
};
use frame_system as system;
use sp_core::H256;
use sp_membership::traits::IsOriginAllowedToUseIdty;
use sp_membership::OriginPermission;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
};
type AccountId = u64;
type BlockNumber = u64;
type Block = frame_system::mocking::MockBlock<Test>;
pub type IdtyId = u64;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
DefaultMembership: pallet_membership::{Pallet, Call, Event<T>, Storage, Config<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}
impl system::Config for Test {
type BaseCallFilter = Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = BlockNumber;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix;
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
pub struct IsOriginAllowedToUseIdtyImpl;
impl IsOriginAllowedToUseIdty<Origin, IdtyId> for IsOriginAllowedToUseIdtyImpl {
fn is_origin_allowed_to_use_idty(o: &Origin, idty_id: &IdtyId) -> OriginPermission {
match o.clone().into() {
Ok(system::RawOrigin::Root) => OriginPermission::Root,
Ok(system::RawOrigin::Signed(account_id)) if account_id == *idty_id => {
OriginPermission::Allowed
}
_ => OriginPermission::Forbidden,
}
}
}
parameter_types! {
pub const ExternalizeMembershipStorage: bool = false;
pub const MembershipPeriod: BlockNumber = 5;
pub const PendingMembershipPeriod: BlockNumber = 3;
pub const RenewablePeriod: BlockNumber = 2;
pub const RevocationPeriod: BlockNumber = 4;
}
impl pallet_membership::Config for Test {
type IsIdtyAllowedToClaimMembership = ();
type IsIdtyAllowedToRenewMembership = ();
type IsIdtyAllowedToRequestMembership = ();
type IsOriginAllowedToUseIdty = IsOriginAllowedToUseIdtyImpl;
type Event = Event;
type ExternalizeMembershipStorage = ExternalizeMembershipStorage;
type IdtyId = IdtyId;
type OnEvent = ();
type MembershipExternalStorage = ();
type MembershipPeriod = MembershipPeriod;
type PendingMembershipPeriod = PendingMembershipPeriod;
type RenewablePeriod = RenewablePeriod;
type RevocationPeriod = RevocationPeriod;
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext(gen_conf: pallet_membership::GenesisConfig<Test>) -> sp_io::TestExternalities {
GenesisConfig {
system: SystemConfig::default(),
default_membership: gen_conf,
}
.build_storage()
.unwrap()
.into()
}
pub fn run_to_block(n: u64) {
while System::block_number() < n {
DefaultMembership::on_finalize(System::block_number());
System::on_finalize(System::block_number());
System::reset_events();
System::set_block_number(System::block_number() + 1);
System::on_initialize(System::block_number());
DefaultMembership::on_initialize(System::block_number());
}
}
This diff is collapsed.