[NFTs] Offchain mint (#13158)

* Allow to mint with the pre-signed signatures

* Another try

* WIP: test encoder

* Fix the deposits

* Refactoring + tests + benchmarks

* Add sp-core/runtime-benchmarks

* Remove sp-core from dev deps

* Enable full_crypto for benchmarks

* Typo

* Fix

* Update frame/nfts/src/mock.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nfts

* Add docs

* Add attributes into the pre-signed object & track the deposit owner for attributes

* Update docs

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nfts

* Add the number of attributes provided to weights

* Apply suggestions

* Remove dead code

* Remove Copy

* Fix docs

* Update frame/nfts/src/lib.rs

Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update frame/nfts/src/lib.rs

Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

---------

Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: command-bot <>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
Jegor Sidorenko
2023-02-14 10:19:50 +02:00
committed by GitHub
parent ea70fbc7a6
commit 3b767e1238
14 changed files with 1754 additions and 759 deletions
+61 -5
View File
@@ -67,6 +67,7 @@ pub mod pallet {
use super::*;
use frame_support::{pallet_prelude::*, traits::ExistenceRequirement};
use frame_system::pallet_prelude::*;
use sp_runtime::traits::{IdentifyAccount, Verify};
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
@@ -167,10 +168,24 @@ pub mod pallet {
#[pallet::constant]
type MaxDeadlineDuration: Get<<Self as SystemConfig>::BlockNumber>;
/// The max number of attributes a user could set per call.
#[pallet::constant]
type MaxAttributesPerCall: Get<u32>;
/// Disables some of pallet's features.
#[pallet::constant]
type Features: Get<PalletFeatures>;
/// Off-Chain signature type.
///
/// Can verify whether an `Self::OffchainPublic` created a signature.
type OffchainSignature: Verify<Signer = Self::OffchainPublic> + Parameter;
/// Off-Chain public key.
///
/// Must identify as an on-chain `Self::AccountId`.
type OffchainPublic: IdentifyAccount<AccountId = Self::AccountId>;
#[cfg(feature = "runtime-benchmarks")]
/// A set of helper functions for benchmarking.
type Helper: BenchmarkHelper<Self::CollectionId, Self::ItemId>;
@@ -591,6 +606,14 @@ pub mod pallet {
AlreadyClaimed,
/// The provided data is incorrect.
IncorrectData,
/// The extrinsic was sent by the wrong origin.
WrongOrigin,
/// The provided signature is incorrect.
WrongSignature,
/// The provided metadata might be too long.
IncorrectMetadata,
/// Can't set more attributes per one call.
MaxAttributesLimitReached,
}
#[pallet::call]
@@ -742,10 +765,8 @@ pub mod pallet {
) -> DispatchResult {
let caller = ensure_signed(origin)?;
let mint_to = T::Lookup::lookup(mint_to)?;
let collection_config = Self::get_collection_config(&collection)?;
let item_settings = collection_config.mint_settings.default_item_settings;
let item_config = ItemConfig { settings: item_settings };
let item_config =
ItemConfig { settings: Self::get_default_item_settings(&collection)? };
Self::do_mint(
collection,
@@ -1325,7 +1346,15 @@ pub mod pallet {
value: BoundedVec<u8, T::ValueLimit>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
Self::do_set_attribute(origin, collection, maybe_item, namespace, key, value)
Self::do_set_attribute(
origin.clone(),
collection,
maybe_item,
namespace,
key,
value,
origin,
)
}
/// Force-set an attribute for a collection or item.
@@ -1768,6 +1797,33 @@ pub mod pallet {
witness_price,
)
}
/// Mint an item by providing the pre-signed approval.
///
/// Origin must be Signed.
///
/// - `mint_data`: The pre-signed approval that consists of the information about the item,
/// its metadata, attributes, who can mint it (`None` for anyone) and until what block
/// number.
/// - `signature`: The signature of the `data` object.
/// - `signer`: The `data` object's signer. Should be an owner of the collection.
///
/// Emits `Issued` on success.
/// Emits `AttributeSet` if the attributes were provided.
/// Emits `ItemMetadataSet` if the metadata was not empty.
#[pallet::call_index(37)]
#[pallet::weight(T::WeightInfo::mint_pre_signed(mint_data.attributes.len() as u32))]
pub fn mint_pre_signed(
origin: OriginFor<T>,
mint_data: PreSignedMintOf<T, I>,
signature: T::OffchainSignature,
signer: T::AccountId,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let msg = Encode::encode(&mint_data);
ensure!(signature.verify(&*msg, &signer), Error::<T, I>::WrongSignature);
Self::do_mint_pre_signed(origin, mint_data, signer)
}
}
}