git.delta.rocks / unique-network / refs/commits / 5b6d2a314e03

difftreelog

Merge branch 'master' into dev

Greg Zaitsev2020-07-30parents: #a3fcd2f #b6babd2.patch.diff
in: master

5 files changed

modifiedCargo.lockdiffbeforeafterboth
3085dependencies = [3085dependencies = [
3086 "frame-support",3086 "frame-support",
3087 "frame-system",3087 "frame-system",
3088 "pallet-transaction-payment",
3088 "parity-scale-codec",3089 "parity-scale-codec",
3089 "sp-core",3090 "sp-core",
3090 "sp-io",3091 "sp-io",
3091 "sp-runtime",3092 "sp-runtime",
3093 "sp-std",
3092]3094]
30933095
3094[[package]]3096[[package]]
modifieddoc/application_development.mddiffbeforeafterboth
1616
17![](serverless_architecture.png)17![](serverless_architecture.png)
1818
19## Custom Types for JS API
20
21```
22{
23 "Schedule": {
24 "version": "u32",
25 "put_code_per_byte_cost": "Gas",
26 "grow_mem_cost": "Gas",
27 "regular_op_cost": "Gas",
28 "return_data_per_byte_cost": "Gas",
29 "event_data_per_byte_cost": "Gas",
30 "event_per_topic_cost": "Gas",
31 "event_base_cost": "Gas",
32 "call_base_cost": "Gas",
33 "instantiate_base_cost": "Gas",
34 "dispatch_base_cost": "Gas",
35 "sandbox_data_read_cost": "Gas",
36 "sandbox_data_write_cost": "Gas",
37 "transfer_cost": "Gas",
38 "instantiate_cost": "Gas",
39 "max_event_topics": "u32",
40 "max_stack_height": "u32",
41 "max_memory_pages": "u32",
42 "max_table_size": "u32",
43 "enable_println": "bool",
44 "max_subject_len": "u32"
45 },
46 "NftItemType": {
47 "Collection": "u64",
48 "Owner": "AccountId",
49 "Data": "Vec<u8>"
50 },
51 "CollectionType": {
52 "Owner": "AccountId",
53 "NextItemId": "u64",
54 "Name": "Vec<u16>",
55 "Description": "Vec<u16>",
56 "TokenPrefix": "Vec<u8>",
57 "CustomDataSize": "u32",
58 "Sponsor": "AccountId",
59 "UnconfirmedSponsor": "AccountId"
60 },
61 "Address": "AccountId",
62 "LookupSource": "AccountId",
63 "Weight": "u64"
64}
65```
66
19## NFT Palette Methods67## NFT Palette Methods
2068
21### Collection Management69### Collection Management
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
33branch = 'rc4_ext_dispatch_reenabled'33branch = 'rc4_ext_dispatch_reenabled'
34version = '2.0.0-rc4'34version = '2.0.0-rc4'
35
36[dependencies.sp-std]
37default-features = false
38git = 'https://github.com/usetech-llc/substrate.git'
39branch = 'rc4_ext_dispatch_reenabled'
40version = '2.0.0-rc4'
41
42[dependencies.transaction-payment]
43default-features = false
44git = 'https://github.com/usetech-llc/substrate.git'
45package = 'pallet-transaction-payment'
46branch = 'rc4_ext_dispatch_reenabled'
47version = '2.0.0-rc4'
3548
36[package]49[package]
37authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']50authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
52 'frame-support/std',65 'frame-support/std',
53 'frame-system/std',66 'frame-system/std',
54 'sp-runtime/std',67 'sp-runtime/std',
68 'sp-std/std',
55]69]
5670
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
4/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs4/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
55
6use codec::{Decode, Encode};6use codec::{Decode, Encode};
7use frame_support::{decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure};7pub use frame_support::{
8 decl_event, decl_module, decl_storage,
9 construct_runtime, parameter_types,
10 traits::{Currency, Get, ExistenceRequirement, KeyOwnerProofSystem, OnUnbalanced, Randomness, WithdrawReason, Imbalance},
11 weights::{
12 DispatchInfo, PostDispatchInfo, constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
13 IdentityFee, Weight, WeightToFeePolynomial, GetDispatchInfo, Pays,
14 },
15 StorageValue,
16 dispatch::DispatchResult,
17 IsSubType,
18 ensure
19};
20
8use frame_system::{self as system, ensure_signed};21use frame_system::{self as system, ensure_signed};
9use sp_runtime::sp_std::prelude::Vec;22use sp_runtime::sp_std::prelude::Vec;
23use sp_std::prelude::*;
24use sp_runtime::{
25 FixedU128, FixedPointOperand,
26 transaction_validity::{
27 TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, TransactionValidity
28 },
29 traits::{
30 Saturating, Dispatchable, DispatchInfoOf, PostDispatchInfoOf, SignedExtension, Zero, SaturatedConversion,
31 },
32};
1033
11#[cfg(test)]34#[cfg(test)]
12mod mock;35mod mock;
49 pub description: Vec<u16>, // 256 include null escape char72 pub description: Vec<u16>, // 256 include null escape char
50 pub token_prefix: Vec<u8>, // 16 include null escape char73 pub token_prefix: Vec<u8>, // 16 include null escape char
51 pub custom_data_size: u32,74 pub custom_data_size: u32,
75 pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
76 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
52}77}
5378
54#[derive(Encode, Decode, Default, Clone, PartialEq)]79#[derive(Encode, Decode, Default, Clone, PartialEq)]
195 decimal_points: decimal_points,221 decimal_points: decimal_points,
196 token_prefix: prefix,222 token_prefix: prefix,
197 next_item_id: next_id,223 next_item_id: next_id,
198 custom_data_size: custom_data_size,224 custom_data_size: custom_data_sz,
225 sponsor: T::AccountId::default(),
226 unconfirmed_sponsor: T::AccountId::default(),
199 };227 };
200228
201 // Add new collection to map229 // Add new collection to map
271 }299 }
272300
273 #[weight = 0]301 #[weight = 0]
302 pub fn set_collection_sponsor(origin, collection_id: u64, new_sponsor: T::AccountId) -> DispatchResult {
303
304 let sender = ensure_signed(origin)?;
305 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
306
307 let mut target_collection = <Collection<T>>::get(collection_id);
308 ensure!(sender == target_collection.owner, "You do not own this collection");
309
310 target_collection.unconfirmed_sponsor = new_sponsor;
311 <Collection<T>>::insert(collection_id, target_collection);
312
313 Ok(())
314 }
315
316 #[weight = 0]
317 pub fn confirm_sponsorship(origin, collection_id: u64) -> DispatchResult {
318
319 let sender = ensure_signed(origin)?;
320 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
321
322 let mut target_collection = <Collection<T>>::get(collection_id);
323 ensure!(sender == target_collection.unconfirmed_sponsor, "This address is not set as sponsor, use setCollectionSponsor first");
324
325 target_collection.sponsor = target_collection.unconfirmed_sponsor;
326 target_collection.unconfirmed_sponsor = T::AccountId::default();
327 <Collection<T>>::insert(collection_id, target_collection);
328
329 Ok(())
330 }
331
332 #[weight = 0]
333 pub fn remove_collection_sponsor(origin, collection_id: u64) -> DispatchResult {
334
335 let sender = ensure_signed(origin)?;
336 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
337
338 let mut target_collection = <Collection<T>>::get(collection_id);
339 ensure!(sender == target_collection.owner, "You do not own this collection");
340
341 target_collection.sponsor = T::AccountId::default();
342 <Collection<T>>::insert(collection_id, target_collection);
343
344 Ok(())
345 }
346
347
348
349 #[weight = 0]
274 pub fn create_item(origin, collection_id: u64, properties: Vec<u8>, owner: T::AccountId) -> DispatchResult {350 pub fn create_item(origin, collection_id: u64, properties: Vec<u8>) -> DispatchResult {
275351
276 let sender = ensure_signed(origin)?;352 let sender = ensure_signed(origin)?;
277353
590}666}
667
668
669////////////////////////////////////////////////////////////////////////////////////////////////////
670// Economic models
671
672/// Fee multiplier.
673pub type Multiplier = FixedU128;
674
675type BalanceOf<T> =
676 <<T as transaction_payment::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
677type NegativeImbalanceOf<T> = <<T as transaction_payment::Trait>::Currency as Currency<
678 <T as system::Trait>::AccountId,>>::NegativeImbalance;
679
680
681
682/// Require the transactor pay for themselves and maybe include a tip to gain additional priority
683/// in the queue.
684#[derive(Encode, Decode, Clone, Eq, PartialEq)]
685pub struct ChargeTransactionPayment<T: transaction_payment::Trait + Send + Sync>(#[codec(compact)] BalanceOf<T>);
686
687impl<T:Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T> {
688 #[cfg(feature = "std")]
689 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
690 write!(f, "ChargeTransactionPayment<{:?}>", self.0)
691 }
692 #[cfg(not(feature = "std"))]
693 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
694 Ok(())
695 }
696}
697
698impl<T:Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T> where
699 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<Module<T>, T>,
700 BalanceOf<T>: Send + Sync + FixedPointOperand,
701{
702 /// utility constructor. Used only in client/factory code.
703 pub fn from(fee: BalanceOf<T>) -> Self {
704 Self(fee)
705 }
706
707 pub fn traditional_fee(
708 len: usize,
709 info: &DispatchInfoOf<T::Call>,
710 tip: BalanceOf<T>,
711 ) -> BalanceOf<T> where
712 T::Call: Dispatchable<Info=DispatchInfo>,
713 {
714 <transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
715 }
716
717 fn withdraw_fee(
718 &self,
719 who: &T::AccountId,
720 call: &T::Call,
721 info: &DispatchInfoOf<T::Call>,
722 len: usize,
723 ) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {
724 let tip = self.0;
725
726 // Set fee based on call type. Creating collection costs 1 Unique.
727 // All other transactions have traditional fees so far
728 let fee = match call.is_sub_type() {
729 Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
730 _ => Self::traditional_fee(len, info, tip)
731
732 // Flat fee model, use only for testing purposes
733 // _ => <BalanceOf<T>>::from(100)
734 };
735
736 // Determine who is paying transaction fee based on ecnomic model
737 // Parse call to extract collection ID and access collection sponsor
738 let sponsor: T::AccountId = match call.is_sub_type() {
739 Some(Call::create_item(collection_id, _properties)) => {
740 <Collection<T>>::get(collection_id).sponsor
741 },
742 Some(Call::transfer(collection_id, _item_id, _new_owner)) => {
743 <Collection<T>>::get(collection_id).sponsor
744 },
745
746 _ => T::AccountId::default()
747 };
748
749 let mut who_pays_fee: T::AccountId = sponsor.clone();
750 if sponsor == T::AccountId::default() {
751 who_pays_fee = who.clone();
752 }
753
754 // Only mess with balances if fee is not zero.
755 if fee.is_zero() {
756 return Ok((fee, None));
757 }
758
759 match <T as transaction_payment::Trait>::Currency::withdraw(
760 &who_pays_fee,
761 fee,
762 if tip.is_zero() {
763 WithdrawReason::TransactionPayment.into()
764 } else {
765 WithdrawReason::TransactionPayment | WithdrawReason::Tip
766 },
767 ExistenceRequirement::KeepAlive,
768 ) {
769 Ok(imbalance) => Ok((fee, Some(imbalance))),
770 Err(_) => Err(InvalidTransaction::Payment.into()),
771 }
772 }
773}
774
775impl<T:Trait + transaction_payment::Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> where
776 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
777 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<Module<T>, T>,
778{
779 const IDENTIFIER: &'static str = "ChargeTransactionPayment";
780 type AccountId = T::AccountId;
781 type Call = T::Call;
782 type AdditionalSigned = ();
783 type Pre = (BalanceOf<T>, Self::AccountId, Option<NegativeImbalanceOf<T>>, BalanceOf<T>);
784 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
785
786 fn validate(
787 &self,
788 who: &Self::AccountId,
789 call: &Self::Call,
790 info: &DispatchInfoOf<Self::Call>,
791 len: usize,
792 ) -> TransactionValidity {
793 let (fee, _) = self.withdraw_fee(who, call, info, len)?;
794
795 let mut r = ValidTransaction::default();
796 // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which
797 // will be a bit more than setting the priority to tip. For now, this is enough.
798 r.priority = fee.saturated_into::<TransactionPriority>();
799 Ok(r)
800 }
801
802 fn pre_dispatch(
803 self,
804 who: &Self::AccountId,
805 call: &Self::Call,
806 info: &DispatchInfoOf<Self::Call>,
807 len: usize
808 ) -> Result<Self::Pre, TransactionValidityError> {
809 let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
810 Ok((self.0, who.clone(), imbalance, fee))
811 }
812
813 fn post_dispatch(
814 pre: Self::Pre,
815 info: &DispatchInfoOf<Self::Call>,
816 post_info: &PostDispatchInfoOf<Self::Call>,
817 len: usize,
818 _result: &DispatchResult,
819 ) -> Result<(), TransactionValidityError> {
820 let (tip, who, imbalance, fee) = pre;
821 if let Some(payed) = imbalance {
822 let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(
823 len as u32,
824 info,
825 post_info,
826 tip,
827 );
828 let refund = fee.saturating_sub(actual_fee);
829 let actual_payment = match <T as transaction_payment::Trait>::Currency::deposit_into_existing(&who, refund) {
830 Ok(refund_imbalance) => {
831 // The refund cannot be larger than the up front payed max weight.
832 // `PostDispatchInfo::calc_unspent` guards against such a case.
833 match payed.offset(refund_imbalance) {
834 Ok(actual_payment) => actual_payment,
835 Err(_) => return Err(InvalidTransaction::Payment.into()),
836 }
837 }
838 // We do not recreate the account using the refund. The up front payment
839 // is gone in that case.
840 Err(_) => payed,
841 };
842 let imbalances = actual_payment.split(tip);
843 <T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(Some(imbalances.0).into_iter()
844 .chain(Some(imbalances.1)));
845 }
846 Ok(())
847 }
848}
591849
modifiedruntime/src/lib.rsdiffbeforeafterboth
14use sp_api::impl_runtime_apis;14use sp_api::impl_runtime_apis;
15use sp_consensus_aura::sr25519::AuthorityId as AuraId;15use sp_consensus_aura::sr25519::AuthorityId as AuraId;
16use sp_core::{crypto::KeyTypeId, OpaqueMetadata};16use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
17use sp_runtime::traits::{17use sp_runtime::{
18 create_runtime_str, generic, impl_opaque_keys,
19 transaction_validity::{TransactionSource, TransactionValidity},
20 ApplyExtrinsicResult, MultiSignature,
21 traits::{
18 BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, Saturating, Verify,22 BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, Saturating, Verify,
19};23 },
20use sp_runtime::{24};
21 create_runtime_str, generic, impl_opaque_keys,
22 transaction_validity::{TransactionSource, TransactionValidity},
23 ApplyExtrinsicResult, MultiSignature,
24};
25use sp_std::prelude::*;25use sp_std::prelude::*;
26#[cfg(feature = "std")]26#[cfg(feature = "std")]
27use sp_version::NativeVersion;27use sp_version::NativeVersion;
32pub use contracts::Schedule as ContractsSchedule;32pub use contracts::Schedule as ContractsSchedule;
33pub use frame_support::{33pub use frame_support::{
34 construct_runtime, parameter_types,34 construct_runtime, parameter_types,
35 traits::{KeyOwnerProofSystem, Randomness},35 traits::{Currency, Get, ExistenceRequirement, KeyOwnerProofSystem, OnUnbalanced, Randomness, WithdrawReason},
36 weights::{36 weights::{
37 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},37 DispatchInfo, PostDispatchInfo, constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
38 IdentityFee, Weight,38 IdentityFee, Weight, WeightToFeePolynomial, GetDispatchInfo, Pays,
39 },39 },
40 StorageValue,40 StorageValue,
41 dispatch::DispatchResult,
41};42};
43use system::{self as system};
42#[cfg(any(feature = "std", test))]44#[cfg(any(feature = "std", test))]
43pub use sp_runtime::BuildStorage;45pub use sp_runtime::BuildStorage;
44pub use sp_runtime::{Perbill, Permill};46use sp_runtime::{
47 Perbill,
48};
49
228}234}
229235
230parameter_types! {236parameter_types! {
237 // pub const ExistentialDeposit: u128 = 500;
231 pub const ExistentialDeposit: u128 = 500;238 pub const ExistentialDeposit: u128 = 0;
232}239}
233240
234impl balances::Trait for Runtime {241impl balances::Trait for Runtime {
331 system::CheckEra<Runtime>,338 system::CheckEra<Runtime>,
332 system::CheckNonce<Runtime>,339 system::CheckNonce<Runtime>,
333 system::CheckWeight<Runtime>,340 system::CheckWeight<Runtime>,
334 transaction_payment::ChargeTransactionPayment<Runtime>,341 nft::ChargeTransactionPayment<Runtime>,
335);342);
336/// Unchecked extrinsic type as expected by this runtime.343/// Unchecked extrinsic type as expected by this runtime.
337pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;344pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;