git.delta.rocks / unique-network / refs/commits / 88101e4e97a8

difftreelog

refactor review storage hasher security

Yaroslav Bolyukin2021-03-12parent: #5a4a5b7.patch.diff
in: master

1 file changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
403403
404// #endregion404// #endregion
405405
406// # Used definitions
407//
408// ## User control levels
409//
410// chain-controlled - key is uncontrolled by user
411// i.e autoincrementing index
412// can use non-cryptographic hash
413// real - key is controlled by user
414// but it is hard to generate enough colliding values, i.e owner of signed txs
415// can use non-cryptographic hash
416// controlled - key is completly controlled by users
417// i.e maps with mutable keys
418// should use cryptographic hash
419//
420// ## User control level downgrade reasons
421//
422// ?1 - chain-controlled -> controlled
423// collections/tokens can be destroyed, resulting in massive holes
424// ?2 - chain-controlled -> controlled
425// same as ?1, but can be only added, resulting in easier exploitation
426// ?3 - real -> controlled
427// no confirmation required, so addresses can be easily generated
406decl_storage! {428decl_storage! {
407 trait Store for Module<T: Config> as Nft {429 trait Store for Module<T: Config> as Nft {
408430
409 // Private members431 //#region Private members
410 NextCollectionID: CollectionId;432 /// Id of next collection
411 CreatedCollectionCount: u32;433 CreatedCollectionCount: u32;
434 /// Used for migrations
412 ChainVersion: u64;435 ChainVersion: u64;
436 /// Id of last collection token
437 /// Collection id (controlled?1)
413 ItemListIndex: map hasher(identity) CollectionId => TokenId;438 ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId;
439 //#endregion
414440
415 // Chain limits struct441 //#region Chain limits struct
416 pub ChainLimit get(fn chain_limit) config(): ChainLimits;442 pub ChainLimit get(fn chain_limit) config(): ChainLimits;
443 //#endregion
417444
418 // Bound counters445 //#region Bound counters
446 /// Amount of collections destroyed, used for total amount tracking with
447 /// CreatedCollectionCount
419 CollectionCount: u32;448 DestroyedCollectionCount: u32;
449 /// Total amount of account owned tokens (NFTs + RFTs + unique fungibles)
450 /// Account id (real)
420 pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;451 pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;
452 //#endregion
421453
422 // Basic collections454 //#region Basic collections
455 /// Collection info
456 /// Collection id (controlled?1)
423 pub Collection get(fn collection) config(): map hasher(identity) CollectionId => CollectionType<T::AccountId>;457 pub Collection get(fn collection) config(): map hasher(blake2_128_concat) CollectionId => CollectionType<T::AccountId>;
458 /// List of collection admins
459 /// Collection id (controlled?2)
424 pub AdminList get(fn admin_list_collection): map hasher(identity) CollectionId => Vec<T::AccountId>;460 pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::AccountId>;
461 /// Whitelisted collection users
462 /// Collection id (controlled?2), user id (controlled?3)
425 pub WhiteList get(fn white_list): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => bool;463 pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;
426464 //#endregion
427 /// Balance owner per collection map465
466 /// How many of collection items user have
467 /// Collection id (controlled?2), account id (real)
428 pub Balance get(fn balance_count): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => u128;468 pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => u128;
429469
430 /// second parameter: item id + owner account id + spender account id470 /// Amount of items which spender can transfer out of owners account (via transferFrom)
471 /// Collection id (controlled?2), (token id (controlled ?2) + owner account id (real) + spender account id (controlled?3))
431 pub Allowances get(fn approved): double_map hasher(identity) CollectionId, hasher(twox_64_concat) (TokenId, T::AccountId, T::AccountId) => u128;472 pub Allowances get(fn approved): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) (TokenId, T::AccountId, T::AccountId) => u128;
432473
433 /// Item collections474 //#region Item collections
475 /// Collection id (controlled?2), token id (controlled?1)
434 pub NftItemList get(fn nft_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => NftItemType<T::AccountId>;476 pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => NftItemType<T::AccountId>;
477 /// Collection id (controlled?2), owner (controlled?2)
435 pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => FungibleItemType;478 pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;
479 /// Collection id (controlled?2), token id (controlled?1)
436 pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => ReFungibleItemType<T::AccountId>;480 pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => ReFungibleItemType<T::AccountId>;
481 //#endregion
437482
438 /// Index list483 //#region Index list
484 /// Collection id (controlled?2), tokens owner (controlled?2)
439 pub AddressTokens get(fn address_tokens): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => Vec<TokenId>;485 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => Vec<TokenId>;
486 //#endregion
440487
441 /// Tokens transfer baskets488 //#region Tokens transfer rate limit baskets
489 /// (Collection id (controlled?2), who created (real))
442 pub CreateItemBasket get(fn create_item_basket): map hasher(twox_64_concat) (CollectionId, T::AccountId) => T::BlockNumber;490 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => T::BlockNumber;
491 /// Collection id (controlled?2), token id (controlled?2)
443 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;492 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;
493 /// Collection id (controlled?2), owning user (real)
444 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;494 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;
495 /// Collection id (controlled?2), token id (controlled?2)
445 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;496 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;
497 //#endregion
446498
447 // Contract Sponsorship and Ownership499 //#region Contract Sponsorship and Ownership
500 /// Contract address (real)
448 pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => T::AccountId;501 pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => T::AccountId;
502 /// Contract address (real)
449 pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(twox_64_concat) T::AccountId => bool;503 pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(twox_64_concat) T::AccountId => bool;
504 /// (Contract address(real), caller (real))
450 pub ContractSponsorBasket get(fn contract_sponsor_basket): map hasher(twox_64_concat) (T::AccountId, T::AccountId) => T::BlockNumber;505 pub ContractSponsorBasket get(fn contract_sponsor_basket): map hasher(twox_64_concat) (T::AccountId, T::AccountId) => T::BlockNumber;
506 /// Contract address (real)
451 pub ContractSponsoringRateLimit get(fn contract_sponsoring_rate_limit): map hasher(twox_64_concat) T::AccountId => T::BlockNumber;507 pub ContractSponsoringRateLimit get(fn contract_sponsoring_rate_limit): map hasher(twox_64_concat) T::AccountId => T::BlockNumber;
508 /// Contract address (real)
452 pub ContractWhiteListEnabled get(fn contract_white_list_enabled): map hasher(twox_64_concat) T::AccountId => bool; 509 pub ContractWhiteListEnabled get(fn contract_white_list_enabled): map hasher(twox_64_concat) T::AccountId => bool;
510 /// Contract address (real) => Whitelisted user (controlled?3)
453 pub ContractWhiteList get(fn contract_white_list): double_map hasher(twox_64_concat) T::AccountId, hasher(twox_64_concat) T::AccountId => bool; 511 pub ContractWhiteList get(fn contract_white_list): double_map hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) T::AccountId => bool;
512 //#endregion
454 }513 }
455 add_extra_genesis {514 add_extra_genesis {
456 build(|config: &GenesisConfig<T>| {515 build(|config: &GenesisConfig<T>| {
535594
536 fn on_initialize(now: T::BlockNumber) -> Weight {595 fn on_initialize(now: T::BlockNumber) -> Weight {
537
538 if ChainVersion::get() < 2
539 {
540 let value = NextCollectionID::get();
541 CreatedCollectionCount::put(value);
542 ChainVersion::put(2);
543 }
544
545 0596 0
546 }597 }
578629
579 let chain_limit = ChainLimit::get();630 let chain_limit = ChainLimit::get();
631
632 let created_count = CreatedCollectionCount::get();
633 let destroyed_count = DestroyedCollectionCount::get();
580634
581 // bound Total number of collections635 // bound Total number of collections
582 ensure!(CollectionCount::get() < chain_limit.collection_numbers_limit, Error::<T>::TotalCollectionsLimitExceeded);636 ensure!(created_count - destroyed_count < chain_limit.collection_numbers_limit, Error::<T>::TotalCollectionsLimitExceeded);
583637
584 // check params638 // check params
585 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);639 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);
588 ensure!(token_prefix.len() <= 16, Error::<T>::CollectionTokenPrefixLimitExceeded);642 ensure!(token_prefix.len() <= 16, Error::<T>::CollectionTokenPrefixLimitExceeded);
589643
590 // Generate next collection ID644 // Generate next collection ID
591 let next_id = CreatedCollectionCount::get()645 let next_id = created_count
592 .checked_add(1)646 .checked_add(1)
593 .ok_or(Error::<T>::NumOverflow)?;647 .ok_or(Error::<T>::NumOverflow)?;
594
595 // bound counter
596 let total = CollectionCount::get()
597 .checked_add(1)
598 .ok_or(Error::<T>::NumOverflow)?;
599648
600 CreatedCollectionCount::put(next_id);649 CreatedCollectionCount::put(next_id);
601 CollectionCount::put(total);
602650
603 let limits = CollectionLimits {651 let limits = CollectionLimits {
604 sponsored_data_size: chain_limit.custom_data_limit,652 sponsored_data_size: chain_limit.custom_data_limit,
669 <FungibleTransferBasket<T>>::remove_prefix(collection_id);717 <FungibleTransferBasket<T>>::remove_prefix(collection_id);
670 <ReFungibleTransferBasket<T>>::remove_prefix(collection_id);718 <ReFungibleTransferBasket<T>>::remove_prefix(collection_id);
671719
672 if CollectionCount::get() > 0720 DestroyedCollectionCount::put(DestroyedCollectionCount::get()
673 {
674 // bound couter
675 let total = CollectionCount::get()
676 .checked_sub(1)721 .checked_add(1)
677 .ok_or(Error::<T>::NumOverflow)?;722 .ok_or(Error::<T>::NumOverflow)?);
678
679 CollectionCount::put(total);
680 }
681723
682 Ok(())724 Ok(())
683 }725 }