Гайд з міграції динамічних полів
З випуском Sui 0.13.0 ми замінимо концепцію дочірніх об’єктів на динамічні поля. Це кардинальна зміна, оскільки API переміщення для взаємодії з дочірніми об’єктами в sui::transfer (transfer_to_object і transfer_to_object_id)
видалено та замінено на sui::dynamic_field і sui::dynamic_object_field
для роботи з динамічними полями.
Щоб уникнути помилок у програмах, які використовують дочірні об’єкти, дотримуйтеся наведених нижче інструкцій з міграції та будьте готові внести зміни, коли Devnet оновиться до 0.13.0 (дивіться оголошення #devnet-updates на Discord). Щоб мінімізувати час простою вашої програми, дочекайтеся внесення змін до оновлення Devnet, оскільки до цього часу нові API для взаємодії з динамічними полями будуть недоступні.
Що таке динамічні поля?
Динамічні поля є узагальненням дочірніх об’єктів. Вони дозволяють розробникам Sui Move розширювати свої структури новими даними на льоту.
Вони вирішують основну проблему з дочірніми об’єктами, які вимагають передачі чейну власності свого попередника(батька, батьківського об’єкта і так далі до кореневого об’єкта, яким володіє відправник) через функцію входу. Це обмеження ускладнювало роботу з глибоко вкладеними дочірніми об’єктами та не підтримувало використання, де чейн попередника не міг бути відомий на початку транзакції (тобто динамічне завантаження дочірніх об’єктів). За допомогою динамічних полів у функцію введення передається лише кореневий об’єкт, а доступ до його динамічних полів можна отримати на льоту під час виконання транзакції. (Насправді передача значення динамічного поля як вхідних даних у функцію входу тепер не вдасться).
Вони також мають кілька інших покращень:
- Зберігає будь-яку цінність, а не лише предмети.
- Додавання міток і пошук полів за назвою (де ім’я може бути будь-яким значенням копіювання, видалення, збереження).
- Створення нових мережевих сховищ ключів і значень, таких як Table (однорідні ключі та значення) і Bag (гетерогенні ключі та значення).
Не стримуйтесь в роботі з ними! Ми отримали багато розчарованних відгуків через відсутність структур даних, а потім нездатність реалізувати їх у Move. Тепер ви зможете ефективно впроваджувати всілякі структури даних у Move! Будь то зв’язана хеш-карта, чи префікс trie, чи просто зв’язаний список. Динамічні поля вимагають читання/запису об’єктів у пам’ять. Ми все ще очікуємо, що прості вектори будуть більш ефективними, ніж складні структури даних для дуже невеликої кількості елементів.
Теперішні обмеження
Ми все ще активно працюємо над деякими частинами Dynamic Fields
, але ми не могли дочекатися, щоб поділитися цією функцією з вами, щоб побачити, що ви можете створити з нею, і отримати ваші відгуки. Користуючись цією функцією, слідкуйте за такими відомими проблемами, які буде розглянуто в наступному випуску:
- Видалення для динамічних полів наразі не оптимізовано та не відшкодує повне сховище. Під капотом
dynamic_field
(таdynamic_object_field
) створює об’єктиField
для зберігання своїх пар ключ-значення. - Наразі немає функції
exists_
дляdynamic_fields
, щоб перевірити, чи поле з заданим ім’ям уже визначено в об’єкті. - Існують деякі потенційні проблеми довговічності/узгодженості з об’єктами динамічного поля: якщо валідатор вимикається та повертається під час обробки транзакції з динамічними полями, можливо, він не зможе далі обробляти транзакції з цими об’єктами. Ми активно працюємо над вирішенням цього питання.
Гайд по міграції
Наведені нижче пропозиції допоможуть перетворити будь-яке існуюче використання дочірніх об’єктів на використання динамічних полів, але зауважте, що в багатьох випадках ви можете переосмислити своє використання API. У багатьох випадках код можна зробити простішим або зручнішим для кінцевого користувача. Наведені нижче приклади призначені для того, щоб допомогти з додатковими замінами, щоб допомогти запустити роботу.
Замініть виклики transfer_to_object
на add
// Old, Child Object API
use sui::transfer;
transfer::transfer_to_object(&mut parent, child)
// New, Dynamic Field API
use sui::dynamic_object_field as ofield;
let id = object::id(&child);
ofield::add(&mut parent.id, id, child);
Новий API додає поле до батьківського елемента з ідентифікатором дочірнього елемента як ім’я та дочірнього елемента як значення.
Замініть чейни попередників власності у входу на виклики borrow
, borrow_mut
або remove
(Примітка: ця пропозиція передбачає, що ви виконали попередню пропозицію щодо переходу з transfer_to_object на ofield::add, використовуючи ідентифікатор дочірнього елемента як назву поля).
// Child, Parent, GrandParent are all Objects
struct Child has key, store { id: UID, /* ... */ }
struct Parent has key, store { id: UID, /* ... */ }
struct GrandParent has key, store { id: UID, /* ... */ }
// Old, Child Object API
entry fun read_child(gp: &GrandParent, p: &Parent, c: &Child) {
/* ... */
}
entry fun write_child(gp: &mut GrandParent, p: &mut Parent, c: &mut Child) {
/* ... */
}
entry fun take_child(gp: &mut GrandParent, p: &mut Parent, c: Child) {
/* ... */
}
// New, Dynamic Field API
use sui::dynamic_object_field as ofield;
entry fun read_child(gp: &GrandParent, pid: ID, cid: ID) {
let p = ofield::borrow<ID, Parent>(&gp.id, pid);
let c = ofield::borrow<ID, Child>(&p.id, cid);
/* ... */
}
entry fun write_child(gp: &mut GrandParent, pid: ID, cid: ID) {
let p = ofield::borrow_mut<ID, Parent>(&mut gp.id, pid);
let c = ofield::borrow_mut<ID, Child>(&mut p.id, cid);
/* ... */
}
entry fun take_child(gp: &mut GrandParent, pid: ID, cid: ID) {
let p = ofield::borrow_mut<ID, Parent>(&mut gp.id, pid);
let c = ofield::remove<ID, Child>(&mut p.id, cid);
/* ... */
}
Більше інформації про динамічні поля
Документація про динамічні поля
Більше інформації про Sui
Розробляй разом з нами!!
Ми в захваті від того, як розгортається майбутнє, і запрошуємо авторів і розробників приєднатися до нас.