기본 저장소 마이그레이션

특정 팔레트의 저장소를 수정하고 새로운 저장소 레이아웃으로 마이그레이션하기 위한 준비 방법을 설명합니다.

이 가이드는 FRAME Nicks 팔레트arrow-up-right를 수정하여 특정 팔레트에 대한 저장소 마이그레이션을 수행하는 방법을 설명합니다. 이 튜토리얼에서는 옵션 필드를 포함하는 마지막 이름을 포함하는 저장소 맵을 수정하고, 이후 런타임 업그레이드로 트리거할 수 있는 마이그레이션 함수를 작성합니다. 이러한 유형의 간단한 저장소 마이그레이션은 변경 사항이 특정 팔레트와 개별 저장소 항목에 제한되는 경우에 사용할 수 있습니다. 더 복잡한 데이터 마이그레이션에 대해서는 이 튜토리얼에서 설명하는 것보다 더 복잡한 마이그레이션 함수를 작성하고 마이그레이션을 테스트하기 위해 추가 도구를 사용해야 합니다.

Nicks 팔레트를 로컬에 추가하기

FRAME의 Nicks 팔레트arrow-up-right에서 변경 사항을 가지고 올 것입니다. 런타임에 팔레트 추가하기arrow-up-right 튜토리얼에서는 노드 템플릿에 Nicks 팔레트를 추가하는 방법을 보여줍니다.

이 가이드에서는 팔레트의 코드를 수정하기 때문에 팔레트의 코드를 가져와서 로컬에 추가할 것입니다. 로컬에 추가하는 방법에 대한 예제는 여기arrow-up-right에서 확인할 수 있습니다.

테스트를 위해 노드를 시작하고 Nicks 팔레트 내에서 extrinsic setName을 사용하여 닉네임을 설정할 수 있습니다.

저장소 구조체 생성 및 저장소 항목 업데이트

기본적으로 Nicks 팔레트는 저장소 맵을 사용하여 닉네임을 저장하는 BoundedVec을 포함하는 조회 테이블을 제공합니다. 예를 들어, 기본 저장소 정의는 다음과 같습니다:

/// 이름을 위한 조회 테이블.
	#[pallet::storage]
	pub(super) type NameOf<T: Config> =
		StorageMap<_, Twox64Concat, T::AccountId, (BoundedVec<u8, T::MaxLength>, BalanceOf<T>)>;

저장소를 업데이트하여 옵션 필드를 포함하는 새로운 구조체 Nickname를 만들고 이전 및 새로운 저장소 항목인 이름과 성을 관리합니다:

    #[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen, PartialEqNoBound, RuntimeDebug)]
	#[scale_info(skip_type_params(T))]
	#[codec(mel_bound())]
	pub struct Nickname<T: Config> {
		pub first: BoundedVec<u8, T::MaxLength>,
		pub last: Option<BoundedVec<u8, T::MaxLength>>,
	}

이제 저장소에 저장된 데이터를 변경하기 위해 NameOf StorageMap을 BoundedVec 대신 Nickname 구조체를 저장하도록 업데이트합니다.

함수 업데이트

새로운 데이터 구조체를 추가하고 저장소에 이름과 선택적인 성을 모두 포함하도록 수정한 후에는 Nicks 팔레트 함수를 업데이트하여 새로운 last: Option<BoundedVec<u8>> 매개변수 선언을 포함해야 합니다. 대부분의 경우, 저장소 항목을 수정할 때 함수를 업데이트하려면 변경 사항을 처리하기 위해 일부 로직을 추가해야 합니다. 예를 들어, 매개변수 이름을 수정하거나 새 변수를 추가해야 할 수 있습니다.

이 경우에는 set_nameforce_name 함수에서 대부분의 변경 사항이 필요합니다. 예를 들어, set_name 함수를 수정하여 bounded_namebounded_first로 변경하고 다음과 같은 코드로 bounded_last 선언을 추가할 수 있습니다:

또한, 모든 저장소 쓰기를 Nickname 구조체로 업데이트합니다:

완전한 extrinsic 업데이트 예제는 여기arrow-up-right에서 확인할 수 있습니다.

저장소 버전 추가

pallet::pallet 매크로는 traits::GetStorageVersion을 구현하지만 현재 저장소 버전은 매크로에 전달되어야 합니다. 이를 위해 pallet::storage_version 매크로를 사용할 수 있습니다.

마이그레이션 모듈 선언

마이그레이션 모듈은 두 부분으로 구성되어야 합니다:

  • 마이그레이션할 이전 저장소를 나타내는 모듈

  • 마이그레이션 함수로 가중치를 반환하는 함수

src/pallets/nicks/migration.rs에 새 파일을 생성합니다.

이 모듈의 구조는 다음과 같습니다:

migrate_to_v2 작성

이 함수가 수행해야 할 작업에 대한 개요입니다:

  • 마이그레이션이 필요한지 확인하기 위해 저장소 버전을 확인합니다(좋은 습관).

  • 저장소 값을 새로운 저장소 형식으로 변환합니다.

  • 저장소 버전을 업데이트합니다.

  • 마이그레이션에 소비된 가중치를 반환합니다.

저장소 버전 확인

마이그레이션 로직을 migrate_to_v2 주위에 구성합니다. 저장소 마이그레이션이 필요하지 않은 경우 0을 반환합니다:

저장소 값을 변환

translate storage 메서드arrow-up-right를 사용하여 저장소 값을 새 형식으로 변환합니다. 기존 저장소의 nick 값은 공백으로 구분된 문자열일 수 있으므로, ' '에서 분할하여 새로운 last 저장소 항목에 그 이후의 모든 것을 배치합니다. 그렇지 않은 경우 lastNone 값을 가집니다:

저장소 버전 업데이트

소비된 가중치 반환

이를 위해 저장소 읽기 및 쓰기 수를 계산하고 해당하는 가중치를 반환합니다:

7. on_runtime_upgrade에서 migrate_to_v2 사용

pallet lib.rs에서 mod migration을 선언합니다.

그리고 팔레트의 함수로 돌아가서 on_runtime_upgrade에서 migrate_to_v2 함수를 지정합니다. 이렇게 하면 런타임 업그레이드 시에 어떤 작업이 수행되어야 하는지 표현할 수 있습니다:

전체 마이그레이션 코드 예제는 여기arrow-up-right에서 확인할 수 있습니다.

단위 테스트 업데이트

런타임 마이그레이션 모듈을 작성할 때는 저장소 항목을 망가뜨리는 중대한 문제를 방지하기 위해 테스트하는 것이 중요합니다.

Nicks 팔레트의 테스트는 다음과 같습니다:

  • fn kill_name_should_work()

  • fn force_name_should_work()

  • fn normal_operation_should_work()

  • fn error_catching_should_work()

이러한 테스트를 새로운 코드와 함께 작동하도록 업데이트해야 합니다. 예를 들어:

전체 테스트 수정 예제는 여기arrow-up-right에서 확인할 수 있습니다.

예제

자료

Rust 문서

Last updated