Допис
Діліться своїми знаннями.
Механіка контролю доступу та прийому об'єктів
Це частина 2 серії «Об'єкти батьків-дитини в Sui Move». Ви можете прочитати частину 1 тут
Передача контролю доступу об'єкта: :отримання Механіка
Отже, ви помістили об'єктXвсередині батьківськогоP(передаючи X на ідентифікатор P) - як його повернути або використовувати? 🤔 Ось тут і приходить спеціальний механізм прийому Суй.
Коли об'єкт передається батькові, він автоматично не вискакує. Він знаходиться там, належитьP. Щоб * використати* або * видалити* цей дочірній об'єкт у транзакції, ви повинніотриматийого. Sui надає структурований спосіб зробити це за допомогоюОтримання квит
Подумайте про отримання
Як ви отримуєте отримання
Важливо: Прийом
module example::toy_box {
use sui::transfer::{Self, Receiving};
struct Toy has key { id: UID, name: vector<u8> }
struct Box has key { id: UID }
/// Remove a Toy child from a Box, returning the Toy to the caller.
public entry fun take_toy(box: &mut Box, toy_ticket: Receiving<Toy>): Toy {
// Use the parent's UID and the Receiving ticket to get the Toy
let toy = transfer::receive(&mut box.id, toy_ticket);
// Now `toy` is an owned value we can return (or transfer to someone).
toy
}
}
У take_toy, toy_ticket: Отримання
- Вінперевіряєпід час виконання, що toy_ticket дійсно посилається на об'єкт, який зараз належить полі (використовуючи UID батька). Якщо щось не збігається (неправильний батько або об'єкт, який насправді немає), це буде перервано.
- Потім він повертає фактичний об'єкт Toy як власне значення в транзакції, тобто тепер іграшка знаходиться під контролем нашої функції.
Зверніть увагу, що нам довелося передати &mut box.id. Sui стверджує, що у нас єзмінне посилання на UID батьківдля отримання виклику.
Це розумний контроль доступу: лише модуль, який може створити & mut UID батька, може дозволити отримання. Як правило, модуль визначення батьківського типу відкриває таку функцію, як take_toy, яку отримують внутрішні виклики. Якщо батьківський модуль не відкриває жодної функції, яка видає UID &mut (прямо чи опосередковано), то жоден зовнішній код не зможе вилучити його дочірні дані. Таким чином, батьківський модуль контролює, як і коли можна отримати доступ до дітей.
У прикладі Box має поле id: UID. Оскільки take_toy знаходиться в тому ж модулі, він може запозичити &mut box.id. Зовнішні модулі або транзакції можуть викликати take_toy (box_obj, ticket), але самі не можуть викликати transfer: :receiver на Box, оскільки box.id є приватним.
**Цей шаблон гарантує, що лише авторизований код може отримати дітей.**✅
А як щодо вкладених об'єктів? Якби іграшка була буквально полем всередині коробки (скажімо, Box {id, toy: Toy}), нам не потрібен був би жоден прийом - іграшка була б доступна, коли у вас є &mut Box. Але це також означає, що видалити його або обробити окремо важче (це як частина коробки). З дитячими предметами ми роз'єднуємо сховище: іграшка відокремлена і її потрібно явно вийняти. Ця чіткість є причиною того, що Sui вимагає отримання квитка та отримання дзвінка - це робить пошук дитини дозволеною дією.
Змінювана довідкова вимога: Ви можете задатися питанням, чому &mut UID, а не лише &UID? Mutable гарантує, що батько буде заблоковані під час операції прийому, запобігаючи одночасним змінам та гарантуючи, що абонент насправді має право змінювати цього батька (зазвичай маючи на увазі, що він є власником). Це частина динамічних перевірок власності Sui - беручи змінну позику UID батьків, Sui гарантує, що жодна інша транзакція чи паралельна дія не можуть перешкодити під час вилучення дитини. Це трохи схоже на блокування батьківських дверей перед видаленням вмісту.
Приклад використання в блоці транзакцій: Припустимо, що об'єкт Box належить Алісі, і у неї є об'єкт Toy, який вона хоче помістити в коробку, а потім випадково Вийміть його пізніше. Ось як це могло б бути k:
-Прикріпіть іграшку до коробки: Аліса викликає transfer: :public_transfer (toy, @
Ключові висновки:
- Дочірні об'єкти за замовчуванням недоступні; вам потрібен
квиток прийому та відповідна функція, щоб вивести їх. - Батьківський модуль вирішує, як ви можете отримати (надаючи функцію з &mut UID).
- transfer: :receiver використовується в модулі визначення батьків для об'єктів цього модуля або його друзів. Якщо тип дитини визначено в іншому місці, вам знадобиться інший підхід (введіть public_receiver...).
Перш ніж рухатися далі, ще одна деталь: якщо об'єкт типу T має лише здатність ключа (немає магазину), Sui розглядає його як трохи більш обмежений. Такі об'єкти неможна отримувати за допомогою узагальненого коду поза їх модулем. На практиці це означає, що якщо T є лише ключем і стає дочірнім, вам потрібно буде обробляти його пошук у власному модулі або батьківському модулі за допомогою спеціального правила. Якщо T також має магазин, ми маємо більшу гнучкість через public_receiver. Давайте дослідимо це далі.
- Sui
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.