Publicación
Comparte tu conocimiento.
+15
Fallo en la transacción Sui: objetos reservados para otra transacción
Me encuentro con un problema persistente JsonRpcError
al intentar ejecutar transacciones en Sui. El error indica que los objetos están reservados para otra transacción, aunque he implementado el procesamiento secuencial de las transacciones con retrasos.
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
He intentado:
- Ejecución secuencial de la transacción (esperando a que se complete la transacción anterior)
- Se agregaron retrasos de 3 segundos entre transacciones
Y sigo recibiendo el mismo error de forma constante.
Uso de Sui RPC para el envío de transacciones. El mismo ID de objeto aparece varias veces en la lista de objetos bloqueados. El error se produce incluso con una secuenciación cuidadosa de las transacciones.
- ¿Qué hace que los objetos se «reserven» para otras transacciones?
- ¿Cómo puedo comprobar correctamente si un objeto está disponible antes de usarlo en una transacción?
- ¿Existen mejores prácticas para gestionar los bloqueos de objetos en Sui?
- ¿Podría estar relacionado con el tiempo de finalización de la transacción?
¿Alguien se ha encontrado con este problema antes? ¡Cualquier información sobre la gestión adecuada de objetos en las transacciones de Sui sería muy apreciada!
- Sui
- Transaction Processing
- Move
Respuestas
8Sui utiliza uncontrol de concurrencia optimista, lo que significa que los objetos se bloquean cuando se utilizan en una transacción hasta que la transacción finalice o caduque.
Aunque esperes 3 segundos entre una transacción y otra, si la anterior no se ha finalizado, el objeto permanece bloqueado. Esto significa que la transacción sigue pendiente y tiene acceso exclusivo al objeto.
Cómo comprobar si un objeto está disponible
Utilice el método Sui RPC:
sui_getObject
Compruebe la respuesta para "status": "Locked"
o"owner": "locked"
.
Ejemplo de solicitud:
{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getObject",
"params": ["0x...object_id..."]
}
Si está bloqueado, espera un poco más y vuelve a intentarlo más tarde.
Oye, estás intentando realizar una transacción demasiado rápido y los objetos se han bloqueado.
Intenta enviar una transacción con los mismos objetos a la vez. Si envías dos transacciones, es posible que algunos validadores acepten la primera, otros acepten la segunda y tus objetos se bloquearán porque cada transacción necesita un 66,7% de validadores y es posible que solo obtengas el 50%.
=> espera a que se restablezca la época, ¡es pronto
Consulta más información: https://forums.sui.io/t/beginner-tutorial-error-when-deploying-simple-sui-package/44842
El error significa que los objetos que usa tu transacción siguen bloqueados por transacciones anteriores que aún no se han finalizado. Incluso con retrasos, los objetos permanecen reservados hasta que esas transacciones se completen en cadena.
Para solucionarlo:
- Confirme siempre que las transacciones anteriores relacionadas con los objetos se hayan finalizado por completo antes de volver a utilizarlos.
- Comprueba el estado de los objetos a través de Sui RPC para asegurarte de que están desbloqueados.
- Evite enviar transacciones paralelas o rápidas sobre los mismos objetos.
- Implemente los reintentos con comprobaciones de finalización y retroceso en lugar de demoras fijas.
Este bloqueo evita actualizaciones conflictivas y es normal en el modelo de objetos de Sui. JsonRpcError
La secuenciación adecuada y la confirmación de la finalidad son fundamentales para evitarlo.
Este error se produce si intenta ejecutar dos transacciones simultáneamente (por ejemplo, iniciar una antes de que finalice la anterior). Si vuelves a intentar ejecutar la transacción de publicación sin ejecutar otra transacción antes o al mismo tiempo, debería realizarse correctamente. También es posible que tengas que sacar más gasolina del grifo (o esperar un día, a que pase la época, a que los objetos se desbloqueen)
Cuando realizas una transacción en la que intervienen objetos de tu dirección (como los objetos de gas), los validadores reservan la última versión del objeto para que la utilice la transacción que está firmando. Si intentas ejecutar dos transacciones simultáneamente y se refieren al mismo objeto, competirán entre sí por las firmas de los validadores. En este caso, una de las transacciones gana y se ejecuta, y la otra no consigue suficientes firmas. En el caso desafortunado, es posible que ambas transacciones no obtengan suficientes firmas (si ambas obtuvieron más de un tercio de las firmas del validador, ninguna de las dos podrá superar los dos tercios, que es el umbral), esto se denomina equívoco y, a partir de ese momento, los objetos que sirvieron de entrada a ambas transacciones no se pueden utilizar para ninguna otra transacción.
Al final de la época (duran aproximadamente un día; puedes comprobar el progreso hasta el siguiente cambio de época en https://suiexplorer.com), se liberan todos los bloqueos, por lo que puedes volver a utilizar los objetos, pero si no has cambiado de época desde la última vez que lo intentaste, necesitarás adquirir más gas.
En la red Sui, cuando una transacción intenta acceder a un objeto que ya está involucrado en otra transacción en curso, la red devuelve un error de reserva. Esto es una consecuencia directa del modelo de ejecución centrado en objetos de Sui. Cualquier transacción que mute o consuma un objeto debe adquirir un bloqueo exclusivo sobre él. Una vez que se envía una transacción de este tipo, el objeto permanece reservado hasta que la transacción finalice. Esta reserva evita que otras transacciones interactúen con el mismo objeto de forma prematura, lo que garantiza la atomicidad y evita las condiciones de competencia. Sin embargo, si la finalización se retrasa debido a la latencia de la red, al retraso del validador o a un comportamiento de ejecución inesperado, el objeto puede permanecer bloqueado durante más tiempo del previsto.
Para determinar si un objeto está en estado utilizable, puede utilizar el sui_getObject
método a través de la interfaz JSON-RPC de Sui o la CLI de Sui. Examinar el campo propietario del objeto o los metadatos del bloqueo de la transacción puede proporcionar claridad sobre su estado. Si el objeto parece estar en uso o no devuelve la propiedad a la dirección esperada, es probable que aún esté reservado. Un enfoque aún más sólido consiste en sondear la red mediante programación hasta que se libere el bloqueo del objeto, lo que resulta especialmente útil en los flujos automatizados o cuando se organizan varias transacciones secuenciales.
La gestión eficaz de estos bloqueos exige unas cuantas prácticas clave. Es fundamental evitar la reutilización de objetos mutables en las transacciones hasta que las operaciones anteriores que los afecten estén completamente finalizadas. Siempre que sea posible, deberías considerar la posibilidad de usar monedas de gas e instancias de objetos separadas o rotativas para reducir la controversia. Además, la incorporación de la lógica de reintento y los mecanismos de sondeo inteligentes, como el retraso exponencial, puede minimizar las tasas de error en las transacciones. Cuando las transacciones se organizan en paralelo, aislar el uso de los objetos por proceso o subproceso mejora considerablemente la confiabilidad.
Es importante tener en cuenta que este comportamiento está íntimamente relacionado con la finalidad de la transacción. Aunque se acepte una transacción en el mempool y se emita, los bloqueos de objetos asociados permanecen en su lugar hasta que el quórum de validadores de la red confirme el estado final de la transacción. Cualquier intento de reutilizar ese objeto de antemano, independientemente del uso de demoras arbitrarias basadas en el tiempo, probablemente provocará un error de reserva.
Para agilizar el manejo del bloqueo de objetos, aquí tienes una utilidad de Bash que puedes usar en tu flujo de trabajo de desarrollo. Sondea el nodo completo y espera a que los objetos se desbloqueen antes de continuar con una transacción. Esto garantiza que el objeto se pueda reutilizar de forma segura y mitiga las fallas prematuras.
Secuencia de comandos 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 "$@"
Para usar el script, simplemente hágalo ejecutable y proporcione los ID de objeto que desea rastrear. Sondeará hasta que esos objetos dejen de estar reservados para las transacciones pendientes, con lo que se asegurará de que la próxima transacción se lleve a cabo sin problemas.
chmod +x wait-for-unlock.sh
./wait-for-unlock.sh 0xYOUR_OBJECT_ID
Este tipo de automatización es especialmente eficaz cuando se integra en scripts de implementación o canalizaciones de CI/CD, ya que proporciona una capa de resiliencia en aplicaciones multiusuario o de alto rendimiento.
Simplemente eres su error debido al hecho de que estás intentando ejecutar más de una transacción a la vez, probablemente intentando enviar transacciones agrupadas.
1.** ¿Qué hace que los objetos se «reserven» para otras transacciones?**
Respuesta: Ese error significa que tu transacción ha intentado utilizar un objeto (token, nft, etc.), en este caso, tu moneda de gas (tx.gas
), que ya está «bloqueado» por otra transacción en vuelo en la red Sui.
Los objetos Sui son de un solo uso por transacción y, hasta que no se confirme o caduque la transacción que los bloquea, no podrás volver a usarlos de inmediato (es decir, cuando envíes una transacción recientemente, es posible que la red la esté procesando, por lo que la moneda se reserva temporalmente hasta que la transacción se ejecute por completo).
2.** ¿Cómo puedo comprobar correctamente si un objeto está disponible antes de usarlo en una transacción?**
Respuesta: esperas a que tu primera transacción se complete o falle, esto significa que la moneda de gas (tx.gas
) reservada temporalmente por la red se liberará cuando la transacción se complete o cuando falle. Puedes comprobar el estado de la transacción usando:
bash
sui client tx-status <digest>
3.** ¿Existen mejores prácticas para gestionar los bloqueos de objetos en Sui?**
Respuesta: sí, la hay. Espera a que la transacción anterior finalice o falle (puede tardar hasta 20 segundos en testnet) antes de ejecutar una nueva transacción, y siempre puedes confirmar que la transacción ya se ha completado antes de ejecutar una nueva transacción. También puedes intentarlo de SPLIT YOUR SUI INTO MULTIPLE GAS COINS
esta manera, incluso si una moneda está bloqueada, puedes usar otra inmediatamente usando
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));
Ejecútelo una vez y tendrá varias monedas pequeñas de gasolina en su cuenta.
4.** ¿Podría estar relacionado con el tiempo de finalización de la transacción?**
Respuesta: Sí, esto está relacionado con la finalización de la transacción. Supongo que los retrasos adicionales de 3 segundos entre las transacciones no son suficientes para que una transacción se finalice por completo. Siempre puedes comprobar el estado de la transacción usando sui client tx-status <digest>
El error que se produce se debe al mecanismo de bloqueo de transacciones de Sui, que evita el doble gasto y garantiza las operaciones atómicas. Déjame explicarte exactamente qué está pasando y cómo solucionarlo.
Entendiendo el bloqueo de transacciones en Sui Cuando se envía una transacción a la red Sui, los validadores bloquean los objetos propios a los que se hace referencia para evitar modificaciones simultáneas. Este mecanismo de bloqueo es fundamental para evitar el doble gasto y garantizar la atomización de las transacciones.
Por qué las soluciones actuales no funcionan Su enfoque actual de añadir retrasos de 3 segundos entre las transacciones no es eficaz porque:
- La finalización de la transacción puede tardar más de 3 segundos.
- Es posible que varias transacciones compitan por los mismos objetos.
- La red no garantiza la disponibilidad inmediata de los objetos una vez finalizada la transacción.
Solución paso a paso
- Implemente una verificación adecuada del estado de las transacciones;
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;
}
}
}
-
Verifique la disponibilidad objetiva antes de las transacciones;
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;
}
}
-
Implemente los reintentos de transacciones con retroceso;
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));
}
}
}
Mejores prácticas para la administración de objetos
1.Verifique siempre el estado de la transacción
-
Espere a que se emitan los certificados de validez antes de considerar que las transacciones han finalizado
-
Compruebe el estado de la transacción con regularidad durante el procesamiento
-
Implemente una gestión adecuada de los errores para los objetos bloqueados
2.Comprobaciones de disponibilidad de objetos
-
Verifique la disponibilidad de los objetos antes de crear la transacción
-
Gestione los casos en los que los objetos se bloqueen durante la preparación
-
Considere la posibilidad de implementar mecanismos de reserva de objetos en los contratos inteligentes
3.Secuenciación de transacciones
-
Utilice los certificados de efectos como confirmación de la finalización
-
Implemente un retraso exponencial para los reintentos
-
Mantenga el orden de las transacciones mediante una gestión adecuada de las dependencias
4.Gestión de errores
-
Distinga entre errores de bloqueo temporales y fallos permanentes
-
Implemente una lógica de reintento adecuada con retroceso
-
Mantenga el historial de transacciones con fines de depuración
Consideraciones adicionales
1.Cambios de época
-
Las transacciones pueden fallar durante las transiciones de época
-
Implemente la lógica de reintento específicamente para los errores relacionados con épocas
-
Tenga en cuenta el tiempo de las transacciones en relación con los límites de la época
2.Congestión de red
-
Supervise la carga de la red durante las horas punta
-
Ajuste las estrategias de retroceso en función de las condiciones de la red
-
Considere la posibilidad de implementar un límite de velocidad para las transacciones de alta frecuencia
Al implementar estas soluciones y seguir las prácticas recomendadas descritas anteriormente, deberías poder gestionar de forma eficaz los escenarios de bloqueo de objetos y evitar que se produzca el error JsonRPCError que se esté produciendo. Recuerda que la gestión adecuada de los errores y los mecanismos de reintento son esenciales para un procesamiento fiable de las transacciones en la cadena de bloques Sui.
Este error significa que los objetos que estás utilizando siguen bloqueados por transacciones anteriores que aún no se han finalizado. Incluso con retrasos, Sui los mantiene reservados hasta que la cadena confirme su finalización.
Para solucionarlo, asegúrate de que todas las transacciones anteriores con esos objetos estén completamente finalizadas antes de volver a utilizarlas. Puedes comprobar su estado a través de Sui RPC para ver si están desbloqueados. Evita enviar transacciones múltiples o rápidas que involucren los mismos objetos. En lugar de confiar en demoras fijas, utiliza los reintentos con retraso y confirma la finalidad antes de volver a intentarlo.
Este bloqueo es parte de la forma en que Sui garantiza la seguridad de las actualizaciones, por lo que la secuenciación adecuada y la comprobación de la finalidad son la forma de evitar el error JsonRPCError
Sabes la respuesta?
Inicie sesión y compártalo.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Gana tu parte de 1000 Sui
Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de Sui.

- ¿Por qué BCS requiere un orden de campo exacto para la deserialización cuando las estructuras Move tienen campos con nombre?55
- «Errores de verificación de múltiples fuentes» en las publicaciones del módulo Sui Move: resolución automática de errores45
- Fallo en la transacción Sui: objetos reservados para otra transacción48
- Error de movimiento: no se puede procesar la transacción No se han encontrado monedas de gasolina válidas para la transacción29
- ¿Cómo interactúan las restricciones de capacidad con los campos dinámicos en colecciones heterogéneas?07