Сегодня parity_codec
не поддерживает кодирование u8
во избежание конфликта типов, поскольку Vec<u8>
является частным случаем Vec<T>
.
См .: https://github.com/paritytech/parity-codec/issues/47 < / а>
гавофёрк:
Потому что в противном случае две кодировки: Vec<u8>
и Vec<T: Codec>
конфликтуют.
Возможно, в будущем это можно будет исправить с помощью дополнительных функций Rust, но сейчас вам нужно будет хранить свои отдельные байты как [u8; 1]
и работать с этим типом.
Модуль среды выполнения субстрата
Одно хакерское решение для модуля среды выполнения субстрата выглядит примерно так:
use support::{decl_module, decl_storage, decl_event, StorageValue, dispatch::Result};
use system::ensure_signed;
pub trait Trait: system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
type U8 = [u8; 1];
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
MyByte get(my_byte): U8;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
pub fn set_my_byte(origin, input: U8) -> Result {
let who = ensure_signed(origin)?;
<MyByte<T>>::put(input);
Self::deposit_event(RawEvent::MyByteStored(input, who));
Ok(())
}
pub fn add_to_byte(origin, input: U8) -> Result {
let who = ensure_signed(origin)?;
let my_byte = Self::my_byte()[0];
let my_new_byte = my_byte.checked_add(input[0]).ok_or("Overflow")?;
<MyByte<T>>::put([my_new_byte]);
Self::deposit_event(RawEvent::MyByteStored([my_new_byte], who));
Ok(())
}
}
}
decl_event!(
pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
MyByteStored(U8, AccountId),
}
);
Где мы присваиваем новый тип type U8 = [u8; 1];
. Выбор нашего нового имени типа важен, поскольку он обманывает пользовательский интерфейс Polkadot, чтобы обрабатывать это значение просто как u8
для любых полей ввода / вывода, которые оно генерирует. Если вы попытаетесь использовать настраиваемый тип, например type Byte = [u8; 1]
, пользовательский интерфейс попросит вас импортировать определение этого настраиваемого типа. Если вы попытаетесь использовать [u8; 1]
напрямую, пользовательский интерфейс Polkadot не будет знать, как отображать ввод / вывод этого значения.
Кроме того, на момент написания этого сообщения макрос decl_event!
имеет проблему с внесением [u8; 1]
непосредственно из-за сопоставления с образцом.
Обратите внимание, что вам нужно будет обращаться с этим типом как с массивом, когда вы его используете. add_to_byte()
показывает пример этого. Итак, в конечном итоге вам нужно извлечь первый элемент массива для извлечения байта, и вам нужно обернуть свой байт в массив, чтобы установить U8
:
let my_byte = Self::my_byte()[0];
...
<MyByte<T>>::put([my_new_byte]);
Другие решения могут включать использование других типов, которые изначально поддерживаются, например Vec<u8>
или u16
, и выполнение соответствующих проверок в вашей среде выполнения, чтобы они рассматривались как один u8
, но пользовательский интерфейс не будет знать лучше.
Смарт-контракты субстрата
Я пока не нашел отличного решения для ink!
, но вы сможете использовать [u8; 1]
непосредственно во всем своем коде. Опять же, вам нужно будет рассматривать его как массив для геттеров и сеттеров. Но при создании ABI вам нужно будет вручную изменить экземпляры [u8; 1]
на u8
, чтобы заставить пользовательский интерфейс делать то, что вы хотите.
person
Shawn Tabrizi
schedule
09.05.2019