mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
runtime: remove beefy and mmr from westend (again) (#2972)
* runtime: remove beefy and mmr from westend (again) * node: add borked westend runtime upgrade as bad block
This commit is contained in:
Generated
+155
-155
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,8 @@
|
|||||||
},
|
},
|
||||||
"forkBlocks": null,
|
"forkBlocks": null,
|
||||||
"badBlocks": [
|
"badBlocks": [
|
||||||
"0x53849a2121fe81fde85859dcebe8cc9c37791c01a9702ce65615b1dcb8ac53e5"
|
"0x53849a2121fe81fde85859dcebe8cc9c37791c01a9702ce65615b1dcb8ac53e5",
|
||||||
|
"0x66535350bf0d031dc15a0b6ee20165c0cd7ea49fec85685915f732e24d69e141"
|
||||||
],
|
],
|
||||||
"consensusEngine": null,
|
"consensusEngine": null,
|
||||||
"genesis": {
|
"genesis": {
|
||||||
|
|||||||
@@ -160,7 +160,6 @@ fn westend_session_keys(
|
|||||||
para_validator: ValidatorId,
|
para_validator: ValidatorId,
|
||||||
para_assignment: AssignmentId,
|
para_assignment: AssignmentId,
|
||||||
authority_discovery: AuthorityDiscoveryId,
|
authority_discovery: AuthorityDiscoveryId,
|
||||||
beefy: BeefyId,
|
|
||||||
) -> westend::SessionKeys {
|
) -> westend::SessionKeys {
|
||||||
westend::SessionKeys {
|
westend::SessionKeys {
|
||||||
babe,
|
babe,
|
||||||
@@ -169,7 +168,6 @@ fn westend_session_keys(
|
|||||||
para_validator,
|
para_validator,
|
||||||
para_assignment,
|
para_assignment,
|
||||||
authority_discovery,
|
authority_discovery,
|
||||||
beefy,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +303,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
ValidatorId,
|
ValidatorId,
|
||||||
AssignmentId,
|
AssignmentId,
|
||||||
AuthorityDiscoveryId,
|
AuthorityDiscoveryId,
|
||||||
BeefyId,
|
|
||||||
)> = vec![(
|
)> = vec![(
|
||||||
//5ERCqy118nnXDai8g4t3MjdX7ZC5PrQzQpe9vwex5cELWqbt
|
//5ERCqy118nnXDai8g4t3MjdX7ZC5PrQzQpe9vwex5cELWqbt
|
||||||
hex!["681af4f93073484e1acd6b27395d0d258f1a6b158c808846c8fd05ee2435056e"].into(),
|
hex!["681af4f93073484e1acd6b27395d0d258f1a6b158c808846c8fd05ee2435056e"].into(),
|
||||||
@@ -323,8 +320,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
hex!["d2932edf775088bd088dc5a112ad867c24cc95858f77f8a1ab014de8d4f96a3f"].unchecked_into(),
|
hex!["d2932edf775088bd088dc5a112ad867c24cc95858f77f8a1ab014de8d4f96a3f"].unchecked_into(),
|
||||||
//5GUMj8tnjL3PJZgXoiWtgLCaMVNHBNeSeTqDsvcxmaVAjKn9
|
//5GUMj8tnjL3PJZgXoiWtgLCaMVNHBNeSeTqDsvcxmaVAjKn9
|
||||||
hex!["c2fb0f74591a00555a292bc4882d3158bafc4c632124cb60681f164ef81bcf72"].unchecked_into(),
|
hex!["c2fb0f74591a00555a292bc4882d3158bafc4c632124cb60681f164ef81bcf72"].unchecked_into(),
|
||||||
//5D2gFBzbCNpxTkcqfan1Ra5rmpXDitvd3bHRzbWxvogMJjre
|
|
||||||
hex!["02b123c1695d142ac36d462ca131e0b9c4564ac8ef2726c0d36231d4d690541aa5"].unchecked_into(),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
//5HgDCznTkHKUjzPkQoTZGWbvbyqB7sqHDBPDKdF1FyVYM7Er
|
//5HgDCznTkHKUjzPkQoTZGWbvbyqB7sqHDBPDKdF1FyVYM7Er
|
||||||
@@ -343,8 +338,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
hex!["2ec917690dc1d676002e3504c530b2595490aa5a4603d9cc579b9485b8d0d854"].unchecked_into(),
|
hex!["2ec917690dc1d676002e3504c530b2595490aa5a4603d9cc579b9485b8d0d854"].unchecked_into(),
|
||||||
//5DwBJquZgncRWXFxj2ydbF8LBUPPUbiq86sXWXgm8Z38m8L2
|
//5DwBJquZgncRWXFxj2ydbF8LBUPPUbiq86sXWXgm8Z38m8L2
|
||||||
hex!["52bae9b8dedb8058dda93ec6f57d7e5a517c4c9f002a4636fada70fed0acf376"].unchecked_into(),
|
hex!["52bae9b8dedb8058dda93ec6f57d7e5a517c4c9f002a4636fada70fed0acf376"].unchecked_into(),
|
||||||
//5HXjJatAFhjC2PZdDuWZjtd8BzWdeXMM2TxQCurByaT1RZ15
|
|
||||||
hex!["02c249407413bac607f885f17d9110111ca76395883c68b2773aea13eeefe1a9af"].unchecked_into(),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
//5DMHpkRpQV7NWJFfn2zQxCLiAKv7R12PWFRPHKKk5X3JkYfP
|
//5DMHpkRpQV7NWJFfn2zQxCLiAKv7R12PWFRPHKKk5X3JkYfP
|
||||||
@@ -363,8 +356,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
hex!["1864832dae34df30846d5cc65973f58a2d01b337d094b1284ec3466ecc90251d"].unchecked_into(),
|
hex!["1864832dae34df30846d5cc65973f58a2d01b337d094b1284ec3466ecc90251d"].unchecked_into(),
|
||||||
//5EsSaZZ7niJs7hmAtp4QeK19AcAuTp7WXB7N7gRipVooerq4
|
//5EsSaZZ7niJs7hmAtp4QeK19AcAuTp7WXB7N7gRipVooerq4
|
||||||
hex!["7c1d92535e6d94e21cffea6633a855a7e3c9684cd2f209e5ddbdeaf5111e395b"].unchecked_into(),
|
hex!["7c1d92535e6d94e21cffea6633a855a7e3c9684cd2f209e5ddbdeaf5111e395b"].unchecked_into(),
|
||||||
//5Gw2cEKF3XvYVwyWjXbv347hpkn7DEWfpKJhuFKbBZWEa8kv
|
|
||||||
hex!["021d79fcfa2696cbe13fa3a9f4360293d1defa8725324d7fd1fb73907584ce4fa3"].unchecked_into(),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
//5Ea11qhmGRntQ7pyEkEydbwxvfrYwGMKW6rPERU4UiSBB6rd
|
//5Ea11qhmGRntQ7pyEkEydbwxvfrYwGMKW6rPERU4UiSBB6rd
|
||||||
@@ -383,8 +374,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
hex!["ca5f6b970b373b303f64801a0c2cadc4fc05272c6047a2560a27d0c65589ca1d"].unchecked_into(),
|
hex!["ca5f6b970b373b303f64801a0c2cadc4fc05272c6047a2560a27d0c65589ca1d"].unchecked_into(),
|
||||||
//5EFcjHLvB2z5vd5g63n4gABmhzP5iPsKvTwd8sjfvTehNNrk
|
//5EFcjHLvB2z5vd5g63n4gABmhzP5iPsKvTwd8sjfvTehNNrk
|
||||||
hex!["60cae7fa5a079d9fc8061d715fbcc35ef57c3b00005694c2badce22dcc5a9f1b"].unchecked_into(),
|
hex!["60cae7fa5a079d9fc8061d715fbcc35ef57c3b00005694c2badce22dcc5a9f1b"].unchecked_into(),
|
||||||
//5CfXn3rXE3vxT4oXZcwgKiap4hg457fajgqpGpwuf3MU7ApA
|
|
||||||
hex!["025f644b17a5be19cd8ecacadc86047a6212ce286f16b7775f12571c79934d3c04"].unchecked_into(),
|
|
||||||
)];
|
)];
|
||||||
|
|
||||||
const ENDOWMENT: u128 = 1_000_000 * WND;
|
const ENDOWMENT: u128 = 1_000_000 * WND;
|
||||||
@@ -402,7 +391,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
pallet_beefy: Default::default(),
|
|
||||||
pallet_indices: westend::IndicesConfig { indices: vec![] },
|
pallet_indices: westend::IndicesConfig { indices: vec![] },
|
||||||
pallet_session: westend::SessionConfig {
|
pallet_session: westend::SessionConfig {
|
||||||
keys: initial_authorities
|
keys: initial_authorities
|
||||||
@@ -418,7 +406,6 @@ fn westend_staging_testnet_config_genesis(wasm_binary: &[u8]) -> westend::Genesi
|
|||||||
x.5.clone(),
|
x.5.clone(),
|
||||||
x.6.clone(),
|
x.6.clone(),
|
||||||
x.7.clone(),
|
x.7.clone(),
|
||||||
x.8.clone(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -1310,7 +1297,6 @@ pub fn westend_testnet_genesis(
|
|||||||
ValidatorId,
|
ValidatorId,
|
||||||
AssignmentId,
|
AssignmentId,
|
||||||
AuthorityDiscoveryId,
|
AuthorityDiscoveryId,
|
||||||
BeefyId,
|
|
||||||
)>,
|
)>,
|
||||||
root_key: AccountId,
|
root_key: AccountId,
|
||||||
endowed_accounts: Option<Vec<AccountId>>,
|
endowed_accounts: Option<Vec<AccountId>>,
|
||||||
@@ -1332,7 +1318,6 @@ pub fn westend_testnet_genesis(
|
|||||||
.map(|k| (k.clone(), ENDOWMENT))
|
.map(|k| (k.clone(), ENDOWMENT))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
pallet_beefy: Default::default(),
|
|
||||||
pallet_session: westend::SessionConfig {
|
pallet_session: westend::SessionConfig {
|
||||||
keys: initial_authorities
|
keys: initial_authorities
|
||||||
.iter()
|
.iter()
|
||||||
@@ -1347,7 +1332,6 @@ pub fn westend_testnet_genesis(
|
|||||||
x.5.clone(),
|
x.5.clone(),
|
||||||
x.6.clone(),
|
x.6.clone(),
|
||||||
x.7.clone(),
|
x.7.clone(),
|
||||||
x.8.clone(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -1515,7 +1499,7 @@ fn kusama_development_config_genesis(wasm_binary: &[u8]) -> kusama::GenesisConfi
|
|||||||
fn westend_development_config_genesis(wasm_binary: &[u8]) -> westend::GenesisConfig {
|
fn westend_development_config_genesis(wasm_binary: &[u8]) -> westend::GenesisConfig {
|
||||||
westend_testnet_genesis(
|
westend_testnet_genesis(
|
||||||
wasm_binary,
|
wasm_binary,
|
||||||
vec![get_authority_keys_from_seed("Alice")],
|
vec![get_authority_keys_from_seed_no_beefy("Alice")],
|
||||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -1686,8 +1670,8 @@ fn westend_local_testnet_genesis(wasm_binary: &[u8]) -> westend::GenesisConfig {
|
|||||||
westend_testnet_genesis(
|
westend_testnet_genesis(
|
||||||
wasm_binary,
|
wasm_binary,
|
||||||
vec![
|
vec![
|
||||||
get_authority_keys_from_seed("Alice"),
|
get_authority_keys_from_seed_no_beefy("Alice"),
|
||||||
get_authority_keys_from_seed("Bob"),
|
get_authority_keys_from_seed_no_beefy("Bob"),
|
||||||
],
|
],
|
||||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ pallet-authority-discovery = { git = "https://github.com/paritytech/substrate",
|
|||||||
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-beefy = { git = "https://github.com/paritytech/grandpa-bridge-gadget", branch = "master", default-features = false }
|
|
||||||
pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-elections-phragmen = { package = "pallet-elections-phragmen", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-elections-phragmen = { package = "pallet-elections-phragmen", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
@@ -50,7 +49,6 @@ pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "m
|
|||||||
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
|
||||||
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
pallet-nicks = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
pallet-nicks = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
@@ -121,7 +119,6 @@ std = [
|
|||||||
"pallet-authority-discovery/std",
|
"pallet-authority-discovery/std",
|
||||||
"pallet-authorship/std",
|
"pallet-authorship/std",
|
||||||
"pallet-balances/std",
|
"pallet-balances/std",
|
||||||
"pallet-beefy/std",
|
|
||||||
"pallet-transaction-payment/std",
|
"pallet-transaction-payment/std",
|
||||||
"pallet-transaction-payment-rpc-runtime-api/std",
|
"pallet-transaction-payment-rpc-runtime-api/std",
|
||||||
"pallet-collective/std",
|
"pallet-collective/std",
|
||||||
@@ -133,7 +130,6 @@ std = [
|
|||||||
"pallet-im-online/std",
|
"pallet-im-online/std",
|
||||||
"pallet-indices/std",
|
"pallet-indices/std",
|
||||||
"pallet-membership/std",
|
"pallet-membership/std",
|
||||||
"pallet-mmr/std",
|
|
||||||
"pallet-mmr-primitives/std",
|
"pallet-mmr-primitives/std",
|
||||||
"beefy-primitives/std",
|
"beefy-primitives/std",
|
||||||
"pallet-multisig/std",
|
"pallet-multisig/std",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ use primitives::v1::{
|
|||||||
InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
|
InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
|
||||||
};
|
};
|
||||||
use runtime_common::{
|
use runtime_common::{
|
||||||
mmr as mmr_common, paras_sudo_wrapper, paras_registrar, xcm_sender, slots,
|
paras_sudo_wrapper, paras_registrar, xcm_sender, slots,
|
||||||
SlowAdjustingFeeUpdate, CurrencyToVote,
|
SlowAdjustingFeeUpdate, CurrencyToVote,
|
||||||
impls::ToAuthor,
|
impls::ToAuthor,
|
||||||
BlockHashCount, BlockWeights, BlockLength, RocksDbWeight,
|
BlockHashCount, BlockWeights, BlockLength, RocksDbWeight,
|
||||||
@@ -60,7 +60,8 @@ use xcm_builder::{
|
|||||||
AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter,
|
AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter,
|
||||||
ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete,
|
ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete,
|
||||||
FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom,
|
FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom,
|
||||||
AllowUnpaidExecutionFrom, IsChildSystemParachain, UsingComponents,};
|
AllowUnpaidExecutionFrom, IsChildSystemParachain, UsingComponents,
|
||||||
|
};
|
||||||
|
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
create_runtime_str, generic, impl_opaque_keys,
|
create_runtime_str, generic, impl_opaque_keys,
|
||||||
@@ -102,7 +103,6 @@ pub use pallet_balances::Call as BalancesCall;
|
|||||||
/// Constant values used within the runtime.
|
/// Constant values used within the runtime.
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
use constants::{time::*, currency::*, fee::*};
|
use constants::{time::*, currency::*, fee::*};
|
||||||
use sp_runtime::traits::Keccak256;
|
|
||||||
|
|
||||||
// Weights used in the runtime
|
// Weights used in the runtime
|
||||||
mod weights;
|
mod weights;
|
||||||
@@ -304,7 +304,6 @@ impl_opaque_keys! {
|
|||||||
pub para_validator: ParachainSessionKeyPlaceholder<Runtime>,
|
pub para_validator: ParachainSessionKeyPlaceholder<Runtime>,
|
||||||
pub para_assignment: AssignmentSessionKeyPlaceholder<Runtime>,
|
pub para_assignment: AssignmentSessionKeyPlaceholder<Runtime>,
|
||||||
pub authority_discovery: AuthorityDiscovery,
|
pub authority_discovery: AuthorityDiscovery,
|
||||||
pub beefy: Beefy,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,24 +612,6 @@ impl pallet_sudo::Config for Runtime {
|
|||||||
type Call = Call;
|
type Call = Call;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl pallet_beefy::Config for Runtime {
|
|
||||||
type AuthorityId = BeefyId;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl pallet_mmr::Config for Runtime {
|
|
||||||
const INDEXING_PREFIX: &'static [u8] = b"mmr";
|
|
||||||
type Hashing = Keccak256;
|
|
||||||
type Hash = <Keccak256 as sp_runtime::traits::Hash>::Output;
|
|
||||||
type LeafData = mmr_common::Pallet<Runtime>;
|
|
||||||
type OnNewRoot = mmr_common::DepositBeefyDigest<Runtime>;
|
|
||||||
type WeightInfo = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl mmr_common::Config for Runtime {
|
|
||||||
type BeefyAuthorityToMerkleLeaf = mmr_common::UncompressBeefyEcdsaKeys;
|
|
||||||
type ParachainHeads = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
// One storage item; key size 32, value size 8; .
|
// One storage item; key size 32, value size 8; .
|
||||||
pub const ProxyDepositBase: Balance = deposit(1, 8);
|
pub const ProxyDepositBase: Balance = deposit(1, 8);
|
||||||
@@ -933,11 +914,6 @@ construct_runtime! {
|
|||||||
// Election pallet. Only works with staking, but placed here to maintain indices.
|
// Election pallet. Only works with staking, but placed here to maintain indices.
|
||||||
ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event<T>, ValidateUnsigned} = 24,
|
ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event<T>, ValidateUnsigned} = 24,
|
||||||
|
|
||||||
// Bridges support.
|
|
||||||
Mmr: pallet_mmr::{Pallet, Call, Storage} = 28,
|
|
||||||
Beefy: pallet_beefy::{Pallet, Config<T>, Storage} = 29,
|
|
||||||
MmrLeaf: mmr_common::{Pallet, Storage} = 30,
|
|
||||||
|
|
||||||
// Parachains pallets. Start indices at 40 to leave room.
|
// Parachains pallets. Start indices at 40 to leave room.
|
||||||
ParachainsOrigin: parachains_origin::{Pallet, Origin} = 41,
|
ParachainsOrigin: parachains_origin::{Pallet, Origin} = 41,
|
||||||
ParachainsConfiguration: parachains_configuration::{Pallet, Call, Storage, Config<T>} = 42,
|
ParachainsConfiguration: parachains_configuration::{Pallet, Call, Storage, Config<T>} = 42,
|
||||||
|
|||||||
Reference in New Issue
Block a user