From 251ea62d352ea4ff2994d6a7146ba6c51ea3188b Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Fri, 06 Aug 2021 13:48:42 +0000 Subject: [PATCH] fix: unbroke ink contract build substrate v0.9.8 --- --- a/Cargo.lock +++ b/Cargo.lock @@ -4935,12 +4935,15 @@ name = "nft-data-structs" version = "0.9.0" dependencies = [ + "derivative", "frame-support", "frame-system", + "max-encoded-len", "parity-scale-codec", "serde", "sp-core", "sp-runtime", + "sp-std", ] [[package]] @@ -4999,6 +5002,7 @@ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "derivative", "fp-rpc", "frame-benchmarking", "frame-executive", @@ -5007,6 +5011,7 @@ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "hex-literal", + "max-encoded-len", "nft-data-structs", "pallet-aura", "pallet-balances", --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -1675,8 +1675,8 @@ CreateItemData::NFT(data) => { let item = NftItemType { owner: owner.clone(), - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_nft_item(collection, item)?; @@ -1692,8 +1692,8 @@ let item = ReFungibleItemType { owner: owner_list, - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_refungible_item(collection, item)?; --- a/primitives/nft/Cargo.toml +++ b/primitives/nft/Cargo.toml @@ -9,20 +9,25 @@ version = '0.9.0' [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ['derive'] } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ['derive'] } serde = { version = "1.0.119", features = ['derive'], default-features = false } +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" [features] default = ["std"] std = [ "serde/std", "codec/std", + "max-encoded-len/std", "frame-system/std", "frame-support/std", "sp-runtime/std", "sp-core/std", + "sp-std/std", ] \ No newline at end of file --- a/primitives/nft/src/lib.rs +++ b/primitives/nft/src/lib.rs @@ -4,8 +4,9 @@ use sp_runtime::sp_std::prelude::Vec; use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; pub use frame_support::{ - construct_runtime, decl_event, decl_module, decl_storage, decl_error, + BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error, dispatch::DispatchResult, ensure, fail, parameter_types, traits::{ @@ -19,18 +20,26 @@ }, StorageValue, transactional, }; +use derivative::Derivative; pub const MAX_DECIMAL_POINTS: DecimalPoints = 30; pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000; pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000; pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000; +// TODO: Somehow use ChainLimits for BoundedVec len calculation? +// Do we need ChainLimits anyway, if we can change them via forkless upgrades? +parameter_types! { +pub const MaxDataSize: u32 = 2048; +// TODO: This limit isn't checked for substrate create_multiple_items call +pub const MaxItemsPerBatch: u32 = 200; +} + pub type CollectionId = u32; pub type TokenId = u32; pub type DecimalPoints = u8; -#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum CollectionMode { Invalid, NFT, @@ -60,8 +69,7 @@ fn resolve(who: &AccountId, call: &Call) -> Option; } -#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum AccessMode { Normal, WhiteList, @@ -72,8 +80,7 @@ } } -#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum SchemaVersion { ImageURL, Unique, @@ -84,15 +91,13 @@ } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Ownership { pub owner: AccountId, pub fraction: u128, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum SponsorshipState { /// The fees are applied to the transaction sender Disabled, @@ -147,30 +152,26 @@ pub transfers_enabled: bool, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct NftItemType { pub owner: AccountId, pub const_data: Vec, pub variable_data: Vec, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct FungibleItemType { pub value: u128, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ReFungibleItemType { pub owner: Vec>, pub const_data: Vec, pub variable_data: Vec, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CollectionLimits { pub account_token_ownership_limit: u32, pub sponsored_data_size: u32, @@ -200,8 +201,7 @@ } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ChainLimits { pub collection_numbers_limit: u32, pub account_token_ownership_limit: u32, @@ -219,29 +219,73 @@ pub const_on_chain_schema_limit: u32, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +/// BoundedVec doesn't supports serde +mod bounded_serde { + use core::convert::TryFrom; + use frame_support::{BoundedVec, traits::Get}; + use serde::{ + ser::{self, Serialize}, + de::{self, Deserialize, Error}, + }; + use sp_std::vec::Vec; + + pub fn serialize(value: &BoundedVec, serializer: D) -> Result + where + D: ser::Serializer, + V: Serialize, + { + let vec: &Vec<_> = &value; + vec.serialize(serializer) + } + + pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + V: de::Deserialize<'de>, + S: Get, + { + // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec? + let vec = >::deserialize(deserializer)?; + let len = vec.len(); + TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size")) + } +} + +#[derive( + Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq, Serialize, Deserialize, +)] +#[derivative(Debug)] pub struct CreateNftData { - pub const_data: Vec, - pub variable_data: Vec, + #[serde(with = "bounded_serde")] + #[derivative(Debug="ignore")] + pub const_data: BoundedVec, + #[serde(with = "bounded_serde")] + #[derivative(Debug="ignore")] + pub variable_data: BoundedVec, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, Serialize, Deserialize, +)] pub struct CreateFungibleData { pub value: u128, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq, Serialize, Deserialize, +)] +#[derivative(Debug)] pub struct CreateReFungibleData { - pub const_data: Vec, - pub variable_data: Vec, + #[serde(with = "bounded_serde")] + #[derivative(Debug="ignore")] + pub const_data: BoundedVec, + #[serde(with = "bounded_serde")] + #[derivative(Debug="ignore")] + pub variable_data: BoundedVec, pub pieces: u128, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum CreateItemData { NFT(CreateNftData), Fungible(CreateFungibleData), --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -31,6 +31,7 @@ ] std = [ 'codec/std', + 'max-encoded-len/std', 'cumulus-pallet-aura-ext/std', 'cumulus-pallet-parachain-system/std', 'cumulus-pallet-xcm/std', @@ -378,6 +379,8 @@ # local dependencies [dependencies] +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' } pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' } nft-data-structs = { path = '../primitives/nft', default-features = false, version = '0.9.0' } --- a/runtime/src/chain_extension.rs +++ b/runtime/src/chain_extension.rs @@ -6,6 +6,8 @@ // use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; +use derivative::Derivative; pub use pallet_contracts::chain_extension::RetVal; use pallet_contracts::chain_extension::{ @@ -19,61 +21,63 @@ pub use pallet_nft::*; use pallet_nft::CrossAccountId; use nft_data_structs::*; - -use crate::Vec; /// Create item parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateItem { - pub owner: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtCreateItem { + pub owner: AccountId, pub collection_id: u32, pub data: CreateItemData, } /// Transfer parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransfer { - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransfer { + pub recipient: AccountId, pub collection_id: u32, pub token_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateMultipleItems { - pub owner: ::AccountId, +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] +pub struct NFTExtCreateMultipleItems { + pub owner: AccountId, pub collection_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtApprove { - pub spender: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtApprove { + pub spender: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransferFrom { - pub owner: ::AccountId, - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransferFrom { + pub owner: AccountId, + pub recipient: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] pub struct NFTExtSetVariableMetaData { pub collection_id: u32, pub item_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtToggleWhiteList { +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtToggleWhiteList { pub collection_id: u32, - pub address: ::AccountId, + pub address: AccountId, pub whitelisted: bool, } @@ -82,6 +86,8 @@ pub type NftWeightInfoOf = ::WeightInfo; +pub type AccountIdOf = ::AccountId; + impl ChainExtension for NFTExtension { fn call(func_id: u32, env: Environment) -> Result where @@ -93,7 +99,7 @@ match func_id { 0 => { let mut env = env.buf_in_buf_out(); - let input: NFTExtTransfer = env.read_as()?; + let input: NFTExtTransfer> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -106,13 +112,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 1 => { // Create Item let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateItem = env.read_as()?; + let input: NFTExtCreateItem> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item(input.data.data_size()))?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -124,13 +130,13 @@ input.data, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 2 => { // Create multiple items let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateMultipleItems = env.read_as()?; + let input: NFTExtCreateMultipleItems> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item( input.data.iter().map(|i| i.data_size()).sum(), ))?; @@ -141,16 +147,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, &C::CrossAccountId::from_sub(input.owner), - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 3 => { // Approve let mut env = env.buf_in_buf_out(); - let input: NFTExtApprove = env.read_as()?; + let input: NFTExtApprove> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::approve())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -163,13 +169,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 4 => { // Transfer from let mut env = env.buf_in_buf_out(); - let input: NFTExtTransferFrom = env.read_as()?; + let input: NFTExtTransferFrom> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer_from())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -183,7 +189,7 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 5 => { @@ -198,16 +204,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, input.item_id, - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 6 => { // Toggle whitelist let mut env = env.buf_in_buf_out(); - let input: NFTExtToggleWhiteList = env.read_as()?; + let input: NFTExtToggleWhiteList> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::add_to_white_list())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -219,7 +225,7 @@ input.whitelisted, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } _ => Err(DispatchError::Other("unknown chain_extension func_id")), --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -72,7 +72,6 @@ use sp_runtime::{ traits::{Dispatchable}, }; -// use pallet_contracts::chain_extension::UncheckedFrom; // pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -419,7 +418,7 @@ type DepositPerStorageItem = DepositPerStorageItem; type RentFraction = RentFraction; type SurchargeReward = SurchargeReward; - type WeightPrice = pallet_transaction_payment::Module; + type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = NFTExtension; type DeletionQueueDepth = DeletionQueueDepth; -- gitstuff