Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/migrate nft ownership #921

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open

Fix/migrate nft ownership #921

wants to merge 35 commits into from

Conversation

JasonTulp
Copy link
Contributor

@JasonTulp JasonTulp commented Jan 30, 2025

Description

  • Migrates NFT ownership information into a two storage maps using a multi block migration.
  • First is token-ID -> owner + locks + flags
  • Second is owner -> owned tokens in a collection
  • Migrates PendingIssuances to StorageNMap in NFT and SFT pallets to avoid growing the data with the same data structure as the previous CollectionInfo
  • The multi block migration will re-insert data back to CollectionInfo and migrate only one account per iteration with a max of 50 tokens per iteration. This is to prevent memory leaks while migrating the collections with 800,000 + tokens. Once the collection info has been fully drained of ownership info, it will be re-inserted as the new type

Context & Background

  • The collection Info for an NFT collection is not queryable without using the newly added RPC method. This should make it easier to query that information by separating out the ownership info for an NFT collection. The new approach is optimised for Substrates storage layer.

Notes & Additional Information

  • Everywhere that accesses the NFT collection Info or ownership info must return an error while the migration is ongoing, this is handled largely by the impl of NFTExt within the NFT pallet

Related Issues


Release Notes

Key Changes

Type of Change

  • Runtime Changes
  • Client Changes

API Changes

Storage Changes

Added

  • Nft: TokenInfo
  • Nft: OwnedTokens
  • Nft: NextIssuanceId
  • Sft: NextIssuanceId

Changed

  • Nft: CollectionInfo
  • Nft: PendingIssuances
  • Sft: PendingIssuances

Removed

  • Nft: TokenLocks
  • Nft: TokenUtilityFlags

Storage Migrations

Added

  • Nft Multiblock migration: migrate token ownership
  • Nft migration: remove PendingIssuances
  • Sft Migration: remove PendingIssuances

Copy link
Contributor

@zees-dev zees-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍
Just need CI to pass.

Copy link
Contributor

@zees-dev zees-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Contributor

@surangap surangap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. left some comments. also we might need some bench run for nft pallet now the storage structures are different.

Copy link
Contributor

@surangap surangap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe check other affected pallets also need CI bench runs.

JasonTulp and others added 8 commits February 26, 2025 13:57
…ship

# Conflicts:
#	pallet/common/src/test_utils.rs
#	pallet/nfi/src/mock.rs
#	pallet/nft/src/impls.rs
#	pallet/nft/src/lib.rs
#	pallet/nft/src/mock.rs
#	pallet/nft/src/types.rs
#	pallet/nft/src/weights.rs
#	pallet/xls20/src/mock.rs
#	runtime/src/lib.rs
#	runtime/src/weights/pallet_nft.rs
@JasonTulp JasonTulp requested a review from zees-dev March 5, 2025 22:18
// For simplicity, we will only migrate max 50 tokens from 1 account at a time
if let Some(mut ownership) = old.owned_tokens.pop() {
let mut serial_numbers = ownership.owned_serials.clone();
// take at max 10 from serial_numbers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// take at max MAX_TOKENS_PER_STEP from serial_numbers

}

// Update OwnedTokens with the migrated serials
let _ = pallet_nft::OwnedTokens::<T>::try_mutate(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we ignored the error in owned tokens update

if let Err(e) = pallet_nft::OwnedTokens::::try_mutate(
&ownership.owner,
collection_id,
|owned_serials| -> DispatchResult {
// ...
Ok(())
},
) {
log::error!(target: LOG_TARGET, "🦆 Error updating owned tokens: {:?}", e);
// Consider how to handle this error - maybe mark the migration as failed?
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The try_mutate will never error as we always return Ok(())
In both places where it could have errored, we are using force_push and truncate_from which do not return a Result. These are both safe as the BoundedVec upper bound will not change between the old and new datasets
so it is safe to ignore the result altogether

@@ -134,18 +135,20 @@ pub mod pallet {

// Map from a collection id to a collection's pending issuances
#[pallet::storage]
pub type PendingIssuances<T: Config> = StorageMap<
pub type PendingIssuances<T: Config> = StorageNMap<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesing use of new storage data structure :+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants