Как мне сравнить тип признака со строковым типом в модуле substrate?

#rust #blockchain #substrate

#Ржавчина #блокчейн #субстрат

Вопрос:

Я хочу, чтобы пользователь ввел адрес to:T::AccountIdAccountId , и он будет сравниваться с адресом, который я установил let disable_address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"; . Мой вопрос в том, как мне сравнить эти два разных типа? if (receiver != disable_address) , спасибо.

Мой код

 use frame_support::{decl_storage, decl_module, dispatch::DispatchResult};
use frame_system::ensure_signed;

decl_storage! {
    trait Store for Module<T: Trait> as VerifiableCreds {
        storeValue: u32;
    }
}

decl_module! {
  pub struct Module<T: Trait> for enum Call where origin: T::Origin {
    #[weight = 0]
      fn verify(origin, to:T::AccountId) -> DispatchResult
      {
        let sender = ensure_signed(origin)?;
        let receiver = to;
        let disable_address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
      
        if (receiver != disable_address)
        {
          //do something         
        }
        Ok(())
      }
    
  }
}
 

Ответ №1:

То, что вы предоставили, — это представление адреса SS58, которое не является хорошей отправной точкой для сравнения.

Вместо этого вы должны преобразовать SS58 в его байтовое / шестнадцатеричное представление:

Используя: https://www.shawntabrizi.com/substrate-js-utilities /

 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY

> 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
 

Затем вы хотите сравнить закодированную версию AccountId и посмотреть, соответствует ли она байтовой форме приведенного выше шестнадцатеричного числа:

 let account_bytes: Vec<u8> = to.encode();
let match_bytes: Vec<u8> = hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"].into();

if account_bytes == match_bytes { ... }
 

Что-то в этом роде … но в целом я бы никогда не рекомендовал писать код таким образом. Для начала вы делаете предположение о своей среде выполнения, что ваши учетные записи имеют определенный формат. Представьте себе другую цепочку, которая использует другой формат учетной записи, например, 20-байтовое представление Ethereum, а не 32-байтовое представление. Любая жестко запрограммированная логика, подобная этой, не будет работать.

Вместо этого вы должны предоставить признак конфигурации:

 type DisableAddress: Get<Self::AccountId>;
 

Затем вы должны выполнить сопоставление следующим образом:

 if to == T::DisableAddress::get() { ... }
 

Затем вы должны выполнить ту же логику преобразования байтов, которую я показал выше, во время выполнения.

В этом PR для поддона покупки есть хороший пример именно этого: https://github.com/paritytech/polkadot/pull/1369/files#diff-e5e76e02c0d16e79c70b024cbe3c6ea56f3249382a0f987ba203c34fcb40ed66R954

Комментарии:

1. Очень ценю ваш ответ, он такой полезный. Причина, по которой я жестко запрограммировал логику, заключается в том, что я хочу проверить, может ли он отключить определенный адрес для выполнения передачи (реализовать паллету балансов) в моем новом модуле, если это нарушает наше правило. Но я думаю, что то, что я делаю, бесполезно, потому что учетная запись все еще может передаваться через палитру баланса.

2. Что вы можете сделать, так это создать фильтр, чтобы пользователи не могли напрямую вызывать balances pallet , тогда единственным способом передачи будет ваш pallet.

3. Спасибо за ваш ответ, есть ли какие-либо ресурсы, на которые я могу сослаться?

4. Да, сделайте противоположное этому PR: github.com/paritytech/polkadot/pull/1443/files

5. Действительно ценю ~