怎样为Balances设置Genesis

Genesis 配置定义了诸如帐户、余额、自定义托盘的 Genesis 等事物的初始状态。接下来一起看看使用 2 个简单的存储项目配置pallet的Genesis。

在pallet中实施Genesis

为了我们的目的,假设已经有了 <SingleValue<T>><AccountMap<T>>

例如:

#[pallet::storage]

#[pallet::getter(fn something)]

pub type SingleValue<T: Config> = StorageValue<_, T::Balance>;

// A map that has enumerable entries.

#[pallet::storage]

#[pallet::getter(fn accounts)]

pub type AccountMap<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>;

GenesisConfig 代码应该紧随storage items后面。

  1. 使用 #[pallet::genesis_config] 属性, 为pallet编写 GenesisConfig struct 。

    #[pallet::genesis_config]
    
    pub struct GenesisConfig<T: Config> {
    
    pub single_value: T::Balance,
    
    pub account_map: Vec<(T::AccountId, T::Balance)>,
    
    }
    
  2. GenesisConfig struct设置默认值.

    #[cfg(feature = "std")]
    impl<T: Config> Default for GenesisConfig<T> {
      fn default() -> Self {
          Self { single_value: Default::default(), account_map: Default::default() }
      }
    }
    
  3. 使用 #[pallet::genesis_build] 属性, 实现 GenesisBuild trait。

    #[pallet::genesis_build]
    impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
      fn build(&self) {
          <SingleValue<T>>::put(&self.single_value);
          for (a, b) in &self.account_map {
              <AccountMap<T>>::insert(a, b);
          }
      }
    }
    

    这允许执行一些逻辑来定义GenesisConfig结构如何将一些内容放入到storage中。

设置节点的链规范

接下来要做的是指定我们想要放进链的Genesis state中的值。 假设 pallet 叫做 pallet_something, 声明 PalletSomething 在runtime的construct_runtime! 宏中。

  1. node/chain_spec.rs, 创建一个 T::Balance 类型的值储存在 <SingleValue<T>>中。

    const VALUE: Balance = 235813;
    

    注意,在chain_spec.rs的顶部导入了node_template_runtime::Balance

  2. 创建一个vector并初始化账户信息。

    let accounts_to_map: Vec<AccountId> =
      vec![
          get_account_id_from_seed::<sr25519::Public>("Alice"),
          get_account_id_from_seed::<sr25519::Public>("Bob"),
          get_account_id_from_seed::<sr25519::Public>("Charlie"),
      ];
    
  3. testnet_genesis中完成 GenesisConfig

    通常我们在 runtime/src/lib.rs 里的 construct_runtime!中,使用pallet名称的小写拼写。例如声明为CamelCase的pallet,通常在 testnet_genesis 函数中称其为 camel_case

    在我们的例子中:

    pallet_something: PalletSomethingConfig {
      single_value: VALUE,
      account_map: accounts_to_map.iter().cloned().map(|x| (x, VALUE)).collect(),
    }
    

    在上边的代码中,我们把accounts_to_map 中每个账户和VALUE映射到一起。这和Balances pallet的 GenesisConfig实现非常相似。

实例

  • Node template chain_spec.rs
use node_template_runtime::{
    AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,
    SystemConfig, WASM_BINARY,
};
use sc_service::ChainType;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public};
use sp_finality_grandpa::AuthorityId as GrandpaId;
use sp_runtime::traits::{IdentifyAccount, Verify};

// The URL for the telemetry server.
// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";

/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;

/// Generate a crypto pair from seed.
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
    TPublic::Pair::from_string(&format!("//{}", seed), None)
        .expect("static values are valid; qed")
        .public()
}

type AccountPublic = <Signature as Verify>::Signer;

/// Generate an account ID from seed.
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
    AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
    AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}

/// Generate an Aura authority key.
pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {
    (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))
}

pub fn development_config() -> Result<ChainSpec, String> {
    let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?;

    Ok(ChainSpec::from_genesis(
        // Name
        "Development",
        // ID
        "dev",
        ChainType::Development,
        move || {
            testnet_genesis(
                wasm_binary,
                // Initial PoA authorities
                vec![authority_keys_from_seed("Alice")],
                // Sudo account
                get_account_id_from_seed::<sr25519::Public>("Alice"),
                // Pre-funded accounts
                vec![
                    get_account_id_from_seed::<sr25519::Public>("Alice"),
                    get_account_id_from_seed::<sr25519::Public>("Bob"),
                    get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
                ],
                true,
            )
        },
        // Bootnodes
        vec![],
        // Telemetry
        None,
        // Protocol ID
        None,
        None,
        // Properties
        None,
        // Extensions
        None,
    ))
}

pub fn local_testnet_config() -> Result<ChainSpec, String> {
    let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?;

    Ok(ChainSpec::from_genesis(
        // Name
        "Local Testnet",
        // ID
        "local_testnet",
        ChainType::Local,
        move || {
            testnet_genesis(
                wasm_binary,
                // Initial PoA authorities
                vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")],
                // Sudo account
                get_account_id_from_seed::<sr25519::Public>("Alice"),
                // Pre-funded accounts
                vec![
                    get_account_id_from_seed::<sr25519::Public>("Alice"),
                    get_account_id_from_seed::<sr25519::Public>("Bob"),
                    get_account_id_from_seed::<sr25519::Public>("Charlie"),
                    get_account_id_from_seed::<sr25519::Public>("Dave"),
                    get_account_id_from_seed::<sr25519::Public>("Eve"),
                    get_account_id_from_seed::<sr25519::Public>("Ferdie"),
                    get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
                    get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
                ],
                true,
            )
        },
        // Bootnodes
        vec![],
        // Telemetry
        None,
        // Protocol ID
        None,
        // Properties
        None,
        None,
        // Extensions
        None,
    ))
}

/// Configure initial storage state for FRAME modules.
fn testnet_genesis(
    wasm_binary: &[u8],
    initial_authorities: Vec<(AuraId, GrandpaId)>,
    root_key: AccountId,
    endowed_accounts: Vec<AccountId>,
    _enable_println: bool,
) -> GenesisConfig {
    GenesisConfig {
        system: SystemConfig {
            // Add Wasm runtime to storage.
            code: wasm_binary.to_vec(),
        },
        balances: BalancesConfig {
            // Configure endowed accounts with initial balance of 1 << 60.
            balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
        },
        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),
        },
        transaction_payment: Default::default(),
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值