Genesis 상태 구성하기

Genesis 구성은 계정, 잔액, 커스텀 팔레트의 genesis 등과 같은 스토리지 항목의 초기 상태를 정의합니다. 이 가이드에서는 다음과 같은 스토리지 항목을 가진 팔레트의 genesis 상태를 구성하는 방법을 보여줍니다:

  • 단일 StorageValue 스토리지 항목에 대한 SingleValue<T> 타입.

  • 열거 가능한 항목을 가진 단일 키 StorageMap 스토리지 항목에 대한 AccountMap<T> 타입.

구성 단계 미리보기

  1. 팔레트에 스토리지 항목 추가하기.

  2. 팔레트에 genesis 구성 매크로 추가하기.

  3. 체인 스펙에서 초기 값 설정하기.

팔레트에 스토리지 항목 추가하기

  1. 텍스트 편집기에서 팔레트의 src/lib.rs 파일을 엽니다.

  2. StorageValue 스토리지 항목을 추가합니다.

    예시:

    #[pallet::storage]
    #[pallet::getter(fn something)]
    pub type SingleValue<T: Config> = StorageValue<
       _, 
       T::Balance
    >;
  3. 열거 가능한 항목을 가진 StorageMap 스토리지 항목을 추가합니다.

    예시:

    #[pallet::storage]
    #[pallet::getter(fn accounts)]
    pub type AccountMap<T: Config> = StorageMap<
       _, 
       Blake2_128Concat, 
       T::AccountId, 
       T::Balance
    >;

Genesis 구성 매크로 추가하기

Genesis 구성 매크로는 스토리지 항목 이후에 작성되어야 합니다.

  1. #[pallet::genesis_config] 속성 매크로를 추가하고 초기화할 스토리지 항목에 대한 GenesisConfig 구조체를 정의합니다.

    #[pallet::genesis_config]
    pub struct GenesisConfig<T: Config> {
    	pub single_value: T::Balance,
    	pub account_map: Vec<(T::AccountId, T::Balance)>,
    }
  2. GenesisConfig 구조체의 기본값을 설정합니다.

    #[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 트레이트를 구현합니다.

    #[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);
    		}
    	}
    }

    #[pallet::genesis_build] 매크로를 사용하면 GenesisConfig 구조체가 스토리지에 어떻게 배치되는지를 정의하는 논리를 실행할 수 있습니다.

초기 값 설정하기

팔레트에서 스토리지 항목과 제네시스 구성을 구성한 후, 체인의 제네시스 상태에 설정할 값을 지정할 수 있습니다. 이 예시에서는 런타임의 construct_runtime! 매크로가 팔레트 이름으로 PalletSomething을, 팔레트의 경로로 pallet_something을 참조한다고 가정합니다.

construct_runtime!(
   pub struct Runtime
   where
      Block = Block,
      NodeBlock = opaque::Block,
      UncheckedExtrinsic = UncheckedExtrinsic,
   {
      PalletSomething: pallet_something,
   }
)
  1. 텍스트 편집기에서 node/chain_spec.rs 파일을 엽니다.

  2. chain_spec.rs 파일 상단에 가져온 use node_template_runtime::BalanceConfig;가 있는지 확인합니다.

  3. <SingleValue<T>>에 저장될 T::Balance 타입의 상수 값을 생성합니다 (testnet_genesis 메서드 내부).

    const VALUE: Balance = 235813;
  4. testnet_genesis 메서드 내부에서 <AccountMap<T>>을 초기화하기 위해 사용할 계정 벡터를 생성합니다.

    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"),
    	];
  5. testnet_genesis 함수 내에서 GenesisConfig 절에 팔레트를 추가합니다.

    runtime/src/lib.rsconstruct_runtime! 내에서 팔레트 이름을 소문자로 표기하는 것이 관례입니다. 예를 들어 CamelCase로 선언된 팔레트의 경우, 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 팔레트의 GenesisConfig와 매우 유사합니다.

예시

Last updated