Допис
Діліться своїми знаннями.
+15
Невдала операція Sui: об'єкти, зарезервовані для іншої транзакції
Я стикаюся з наполегли JsonRpcError
вим при спробі виконати транзакції на Sui. Помилка вказує на те, що об'єкти зарезервовані для іншої транзакції, навіть якщо я впровадив послідовну обробку транзакцій із затримками.
JsonRpcError: Failed to sign transaction by a quorum of validators because one or more of its objects is reserved for another transaction. Other transactions locking these objects:
- AV7coSQHWg5vN3S47xada6UiZGW54xxUNhRv1QUPqWK (stake 33.83)
- 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9
- 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9
- 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9
Я пробував:
- Послідовне виконання транзакції (очікування завершення попередньої транза��ції)
- Додані 3-секундні затримки між транзакціями
І все ще отримуємо ту саму помилку послідовно.
Використання Sui RPC для подання транзакцій. Один і той же ідентифікатор об'єкта з'являється кілька разів у списку блокування. Помилка виникає навіть при ретельному послідовності транзакцій.
- Що призводить до того, що об'єкти «зарезервовані» для інших транзакцій?
- Як правильно перевірити наявність об'єкта, перш ніж використовувати його в транзакції?
- Чи існують найкращі методи роботи з блокуванням об'єктів у Sui?
- Чи може це бути пов'язано з термінами остаточності транзакції?
Хтось стикався з цією проблемою раніше? Будь-яка інформація про правильне управління об'єктами в транзакціях Sui буде дуже вдячна!
- Sui
- Transaction Processing
- Move
Відповіді
8Sui використовуєоптимістичний контроль паралельності, тобто об'єкти блокуються, коли вони використовуються в транзакції, поки ця транзакція не буде завершена або закінчиться.
Навіть якщо ви чекаєте 3 секунди між транзакціями, якщо попередня не була завершена, об'єкт залишається заблокованим. Це означає, що транзакція все ще знаходиться в очікуванні та має ексклюзивний доступ до об'єкта.
Як перевірити, чи є об'єкт доступний
Використовуйте метод Sui RPC:
sui_getObject
Перевірте відповідь на "status": "Locked"
або"owner": "locked"
.
Приклад запиту:
{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getObject",
"params": ["0x...object_id..."]
}
Якщо заблоковано, просто зачекайте більше і повторіть спробу пізніше.
Гей, ви намагаєтеся зробити транзакцію занадто швидко, і об'єкти заблоковані.
Спробуйте надіслати одну транзакцію з одними і тими ж об'єктами одночасно, якщо ви надсилаєте дві транзакції, деякі валідатори можуть прийняти першу, деякі можуть прийняти другу, а ваші об'єкти будуть заблоковані, оскільки кожна транзакція потребує 66.7% валідаторів, і ви можете отримати лише 50%.
=> просто дочекайтеся скидання епохи, це скоро
Перевірте більше: https://forums.sui.io/t/beginner-tutorial-error-when-deploying-simple-sui-package/44842
Помилка означає, що об'єкти, які використовує ваша транзакція, все ще заблоковані попередніми транзакціями, які ще не завершені. Навіть із затримками об'єкти залишаються зарезервованими, поки ці транзакції не завершаться в ланцюжку.
Щоб виправити:
- Завжди підтверджуйте, що попередні транзакції, пов'язані з об'єктами, повністю завершені, перш ніж використовувати їх знову.
- Перевірте статус об'єкта за допомогою Sui RPC, щоб переконатися, що вони розблоковані.
- Уникайте відправки паралельних або швидких транзакцій на одних і тих же об'єктах.
- Реалізуйте повторні спроби з перевіркою відмови та остаточності замість фіксованих затримок.
Це блокування запобігає конфліктним оновленням і є нормальним для об'єктної моделі Sui. JsonRpcError
Правильне послідовність та підтвердження остаточності є ключовими для уникнення.
Ця помилка трапляється, якщо ви намагаєтеся запустити дві транзакції одночасно (наприклад, запустити одну до завершення попередньої). Якщо ви повторно спробуєте запустити транзакцію публікації, не запустивши іншу транзакцію до або одночасно, вона повинна бути успішною. Можливо, вам також доведеться придбати більше газу з крана (або почекати день - поки епоха перекинеться - щоб об'єкти розблокуються)
Коли ви виконуєте транзакцію, яка включає об'єкти, якими володіє ваша адреса (наприклад, об'єкти gas), валідатори резервують останню версію об'єкта для використання транзакцією, яку він підписує. Якщо спробувати запустити дві транзакції одночасно і вони посилаються на один і той же об'єкт, то вони будуть конкурувати між собою за підписи від валідаторів. У щасливому випадку одна з транзакцій виграє і виконується, а інша транзакція не отримує достатньої кількості підписів. У нещасному випадку обидві транзакції можуть не отримати достатню кількість підписів (якщо обидві отримали більше третини підписів валідатора, то жодна з них не може отримати більше двох третин, що є пороговим значенням), це називається еквівкацією, і з цього моменту об'єкти, які були введені в обидві транзакції, не можуть бути використані для будь-яких інших транзакцій.
Наприкінці епохи (вони тривають приблизно день - ви можете перевірити прогрес до наступної зміни епохи на https://suiexplorer.com), усі блокування звільняються, тому ви можете використовувати об'єкти знову, але якщо у вас не було зміни епохи з моменту останнього спробування, вам потрібно буде придбати більше газу.
У мережі Sui, коли транзакція намагається отримати доступ до об'єкта, який вже бере участь у іншій транзакції, мережа повертає помилку бронювання. Це прямий наслідок об'єктно-центричної моделі виконання Суї. Будь-яка транзакція, яка мутує або споживає об'єкт, повинна обзавестися ексклюзивним замком на ньому. Після подання такої угоди об'єкт залишається зарезервованим до тих пір, поки транзакція не досягне остаточності. Це застереження запобігає передчасній взаємодії інших транзакцій з тим самим об'єктом, тим самим забезпечуючи атомність та уникаючи умов гонки. Однак, якщо остаточність затримується через затримку мережі, затримку валідатора або несподівану поведінку виконання, об'єкт може залишатися заблокованим довше, ніж очікувалося.
Щоб визначити, чи знаходиться об'єкт у зручному стані, ви можете використовувати sui_getObject
метод через інтерфейс JSON-RPC Sui або Sui CLI. Вивчення поля власника об'єкта або метаданих блокування транзакції може забезпечити чіткість щодо його статусу. Якщо об'єкт, здається, використовується або не повертає право власності на очікувану адресу, він, ймовірно, все одно зарезервований. Ще більш надійний підхід передбачає програмне опитування мережі до моменту звільнення блокування об'єкта - особливо корисно в автоматизованих потоках або при організації кількох послідовних транзакцій.
Ефективне поводження з цими замками вимагає кількох ключових практик. Важливо уникати повторного використання змінних об'єктів між транзакціями, доки попередні операції, пов'язані з ними, не будуть повністю завершені. Вам слід розглянути можливість використання окремих або обертових газових монет та екземплярів предметів, де це можливо, щоб зменшити суперечки. Крім того, включення логіки повторної спроби та інтелектуальних механізмів опитування, таких як експоненціальний зворотний зв'язок, може мінімізувати частоту відмов транзакцій. Коли транзакції організовуються паралельно, ізоляція використання об'єкта за процесом або потоком значно підвищує надійність.
Важливо зазначити, що така поведінка тісно пов'язана з остаточністю транзакції. Навіть якщо транзакція буде прийнята до мепулу та транслюється, пов'язані блокування об'єктів залишаються на місці, доки кворум валідатора мережі не підтвердить остаточний стан транзакції. Будь-яка спроба повторного використання цього об'єкта заздалегідь, незалежно від використання довільних затримок на основі часу, ймовірно, призведе до помилки бронювання.
Щоб спростити обробку блокування об'єктів, ось утиліта Bash, яку ви можете використовувати у своєму робочому процесі розробки. Він опитує fullnode і чекає, поки об'єкти будуть розблоковані, перш ніж продовжити транзакцію. Це гарантує безпеку об'єкта для повторного використання та пом'якшує передчасний збій.
Скрипт Bash: wait-for-unlock.sh
#!/bin/bash
# Sui Fullnode RPC endpoint (adjust as needed)
RPC_ENDPOINT="https://fullnode.testnet.sui.io:443"
# Checks if object is locked
is_locked() {
obj_id=$1
lock_info=$(curl -s -X POST $RPC_ENDPOINT \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "sui_getObject",
"params": ["'"$obj_id"'"],
"id": 1
}')
echo "$lock_info" | grep -q '"owner":{"AddressOwner"' && return 1 || return 0
}
# Waits until each object is no longer locked
wait_for_unlock() {
for obj_id in "$@"; do
echo "Checking object $obj_id..."
while is_locked $obj_id; do
echo "Object $obj_id is still locked. Retrying in 2s..."
sleep 2
done
echo "Object $obj_id is now unlocked."
done
}
# Main handler
main() {
if [ $# -eq 0 ]; then
echo "Usage: $0 <object_id_1> <object_id_2> ..."
exit 1
fi
wait_for_unlock "$@"
echo "All objects unlocked. Safe to proceed with transaction."
}
main "$@"
Щоб скористатися скриптом, просто зробіть його виконуваним і вкажіть ідентифікатори об'єктів, які ви хочете відстежувати. Він буде опитувати, доки ці об'єкти більше не будуть зарезервовані очікуваними транзакціями, гарантуючи безперебійне виконання наступної транзакції.
chmod +x wait-for-unlock.sh
./wait-for-unlock.sh 0xYOUR_OBJECT_ID
Цей тип автоматизації особливо ефективний при інтеграції в скрипти розгортання або конвеєри CI/CD, забезпечуючи рівень стійкості у високопродуктивних або багатокористувацьких додатках.
Ви просто його помилка через те, що ви намагаєтеся запустити відразу більше однієї транзакції, ймовірно, намагаючись відправити пакетні транзакції.
1.Що призводить до того, що об'єкти «зарезервовані» для інших транзакцій?
Відповідь: Ця помилка означає, що ваша транзакція намагалася використовувати об'єкт (токен, nfts тощо), у цьому випадку вашу газову монету (tx.gas
), яка вже «заблокована» іншою транзакцією під час польоту в мережі Sui.
Об'єкти Sui є одноразовими для кожної транзакції, і доки транзакція, яка їх блокує, не буде підтверджена або закінчиться, ви не можете використовувати їх відразу знову (тобто, коли ви нещодавно надсилаєте транзакцію, мережа все ще може обробляти її, тому монета тимчасово зарезервована до повного виконання транзакції).
2.Як я можу правильно перевірити, чи є об'єкт доступний, перш ніж використовувати його в транзакції?
Відповідь: ви чекаєте, поки ваша перша транзакція буде завершена або провалена, це означає, що газова монета (tx.gas
), зарезервована мережею, тимчасово була випущена, коли транзакція завершена або коли вона не вдається. Перевірити статус транзакції можна за допомогою:
bash
sui client tx-status <digest>
3.** Чи існують найкращі методи обробки блокування об'єктів у Sui?**
Відповідь: так, є, Зачекайте, поки попередня транзакція завершиться або не вдасться (може зайняти до 20 секунд у testnet), перш ніж виконати нову транзакцію, і ви завжди можете підтвердити, що ваша транзакція вже завершена, перш ніж виконати нову транзакцію. Ви також можете спробувати SPLIT YOUR SUI INTO MULTIPLE GAS COINS
Таким чином, навіть якщо одна монета заблокована, ви можете негайно використовувати іншу, використовуючи
js
const tx = new Transaction();
const [newGas] = tx.splitCoins(tx.gas, [tx.pure.u64(1_000_000_000n)]); // 1 SUI
tx.transferObjects([newGas], tx.pure.address(ownAddress));
Запустіть його один раз, і у вас буде кілька маленьких газових монет на вашому рахунку.
4.** Чи може це бути пов'язано з термінами остаточності транзакції?**
Відповідь:Так, це пов'язано з остаточністю транзакції, я припускаю, що доданих 3-секундних затримок між транзакціями недостатньо для повного завершення транзакції, ви завжди можете перевірити статус транзакції за допомогою sui client tx-status <digest>
Помилка, з якою ви стикаєтесь, виникає через механізм блокування транзакцій Sui, який запобігає подвійним витратам та забезпечує атомні операції. Дозвольте пояснити, що саме відбувається і як це виправити.
Розуміння блокування транзакцій у SUI Коли транзакція надсилається до мережі Sui, валідатори блокують об'єкти, на які посилаються, щоб запобігти одночасним змінам. Цей механізм блокування є основоположним для запобігання подвійних витрат та забезпечення атомності транзакцій.
Чому поточні рішення не працюють Ваш поточний підхід додавання 3-секундних затримок між транзакціями не є ефективним, оскільки:
- Остаточність транзакції може зайняти більше 3 секунд.
- Кілька транзакцій можуть конкурувати за одні й ті ж об'єкти.
- Мережа не гарантує негайну доступність об'єкта після завершення транзакції.
Покрокове рішення
- Реалізувати належну перевірку статусу транзакції;
async function waitForTransaction(txDigest) {
const MAX_RETRIES = 30;
const RETRY_DELAY_MS = 1000;
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
const result = await suiClient.transactionBlock({
digest: txDigest,
options: { showEffects: true }
});
if (result.status === 'SUCCESS') {
return result;
}
if (attempt === MAX_RETRIES - 1) {
throw new Error(`Transaction ${txDigest} failed`);
}
} catch (error) {
if (error.message.includes('not found')) {
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS));
continue;
}
throw error;
}
}
}
-
Перевірити об'єктивну доступність перед транзакціями;
async function checkObjectAvailability(objectId) {
try {
const result = await suiClient.objects({
ids: [objectId],
options: { showPreviousVersion: true }
});
// Object is available if we can fetch it successfully
return result.details.length > 0;
} catch (error) {
return false;
}
}
-
Реалізувати повторні спроби транзакцій за допомогою Backoff;
async function executeTransactionWithRetry(txBuilder, signer) {
const MAX_RETRIES = 5;
const INITIAL_BACKOFF_MS = 500;
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
const tx = await txBuilder.sign();
const result = await suiClient.submitTransaction(tx);
// Wait for transaction completion
await waitForTransaction(result.digest);
return result;
} catch (error) {
if (attempt === MAX_RETRIES - 1) {
throw error;
}
const backoffMs = INITIAL_BACKOFF_MS * Math.pow(2, attempt);
console.log(`Attempt ${attempt + 1} failed, retrying in ${backoffMs}ms`);
await new Promise(resolve => setTimeout(resolve, backoffMs));
}
}
}
Кращі практики управління об'єктами
1.** Завжди перевіряйте статус транзакції**
-
Зачекайте сертифікатів ефектів, перш ніж вважати транзакції завершеними
-
Регулярно перевіряйте статус транзакції під час обробки
-
Реалізуйте належну обробку помилок для заблокованих об'єктів
2.Перевірка наявності об'єктів
-
Перевірте наявність об'єкта перед створенням транзакції
-
Обробляти випадки, коли предмети замикаються під час підготовки
-
Розглянути можливість впровадження механізмів резервування об'єктів у смарт-контрактах
3.Послідовування транзакцій
-
Використовуйте сертифікати ефектів як підтвердження завершення
-
Реалізуйте експоненціальну відставку для повторних спроб
-
Підтримуйте порядок транзакцій за допомогою належного управління залежностями
4.Обробка помилки
-
Розрізняють тимчасові помилки блокування та постійні збої
-
Реалізуйте правильну логіку повторної спроби з зворотним зв'язком
-
Ведення історії транзакцій для налагодження
Додаткові міркування
1.Зміни епохи
-
Транзакції можуть провалитися під час переходів епохи
-
Реалізувати логіку повторної спроби спеціально для збоїв, пов'язаних з епохою
-
Розглянемо терміни транзакцій щодо меж епохи
2.Перевантаженість мережі
-
Моніторинг навантаження мережі під час пікових періодів
-
Налаштуйте стратегії зворотного відходу на основі умов мережі
-
Подумайте про впровадження обмеження ставок для високочастотних транзакцій
Реалізуючи ці рішення та дотримуючись найкращих практик, описаних вище, ви зможете ефективно обробляти сценарії блокування об'єктів та запобігати JSONRPCError, з якою ви стикаєтесь. Пам'ятайте, що належні механізми обробки помилок та повторної спроби мають важливе значення для надійної обробки транзакцій на блокчейні Sui.
Ця помилка означає, що об'єкти, які ви використовуєте, все ще заблоковані попередніми транзакціями, які ще не завершені. Навіть із затримками Суй зберігає їх зарезервованими, поки ланцюг не підтвердить завершення.
Щоб виправити це, переконайтеся, що всі попередні транзакції з використанням цих об'єктів повністю завершені, перш ніж їх повторно використовувати. Ви можете перевірити їх статус через Sui RPC, щоб побачити, чи вони розблоковані. Уникайте надсилання декількох або швидких транзакцій за участю одних і тих же об'єктів. Замість того, щоб покладатися на фіксовані затримки, використовуйте повторні спроби з відходом і підтвердіть остаточність перед повторною спробою.
Це блокування є частиною того, як Sui забезпечує безпечні оновлення, тому правильне послідовність та перевірка остаточності - це спосіб уникнути JSONRPCError
Ви знаєте відповідь?
Будь ласка, увійдіть та поділіться нею.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Зароби свою частку з 1000 Sui
Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.

- Чому BCS вимагає точного порядку полів для десеріалізації, коли структури Move мають названі поля?55
- Помилки перевірки кількох джерел» у публікаціях модуля Sui Move - автоматичне вирішення помилок45
- Невдала операція Sui: об'єкти, зарезервовані для іншої транзакції48
- Помилка Sui Move - Неможливо обробити транзакцію Не знайдено дійсних газових монет для транзакції29
- Як обмеження здібностей взаємодіють з динамічними полями в гетерогенних колекціях?07