Realizar actualizaciones atómicas en los códigos de cadenas y canales

Puede utilizar transacciones atómicas para completar varias transacciones a través de canales y códigos de cadenas de una manera atómica.

Una transacción atómica es una serie indivisible de operaciones de datos que todas se realizan correctamente o ninguna.

Las transacciones atómicas pueden ser útiles en situaciones complejas en las que se despliegan varios códigos de cadenas en canales independientes. Puede utilizar transacciones atómicas para mantener la consistencia de los datos mientras ejecuta varias transacciones de cadena de bloques, incluso si se produce un fallo de la red o del sistema. Oracle Blockchain Platform soporta transacciones atómicas mediante el protocolo de confirmación en dos fases, donde una fase inicial en la que se prepara cada operación de datos va seguida de una fase en la que se confirma realmente cada operación de datos.

Las transacciones atómicas funcionan a nivel de aplicación. Normalmente, no es necesario cambiar la lógica de código de cadenas existente para soportar transacciones atómicas. Puesto que el marco de transacciones atómicas agrega uno o más argumentos adicionales, asegúrese de que cualquier código de cadena existente no realiza comprobaciones estrictas sobre el número de argumentos transferidos en el método de código de cadena. Las transacciones atómicas están soportadas por el siguiente punto final de API de REST:
  • restproxy/api/v2/atomicTransactions
El punto final de la API de REST prepara las transacciones según lo definido por el código de cadenas y, a continuación, utiliza funciones de código de cadenas incorporadas para confirmar todas las transacciones o para realizar un rollback de todas las transacciones si hay errores durante la fase de preparación. Para obtener más información sobre los puntos finales de REST que se deben utilizar para implantar transacciones atómicas, consulte Puntos finales de REST de transacciones atómicas.

Cada transacción atómica se compone de dos o más transacciones de blockchain. El resultado (el valor returnCode) de la transacción atómica es Success o Failure. En una transacción atómica, cada transacción de blockchain solicitada se divide en dos operaciones distintas: una fase de preparación y, a continuación, una fase de confirmación o una fase de rollback.

  • En la fase de preparación, cada transacción se endosa como de costumbre, pero en lugar de finalizar, los cambios se ubican temporalmente y los valores se bloquean para evitar que otras transacciones modifiquen los valores de ubicación temporal.
  • Si la fase de preparación es correcta para cada transacción de cadena de bloques, las transacciones se avalan y confirman mediante el uso de código de cadenas incorporado. Los valores bloqueados anteriormente se desbloquean y el resultado de la transacción atómica es Success.
  • Si la fase de preparación falla para cualquier transacción de cadena de bloques, se realiza un rollback de todas las demás transacciones en las que la fase de preparación se ha realizado correctamente, de nuevo mediante el uso de código de cadena incorporado. Los cambios almacenados en área temporal se eliminan y los valores bloqueados anteriormente se desbloquean. El resultado de la transacción atómica es Failure.
Debido a que las transacciones atómicas funcionan bloqueando claves, es posible que reciba un error Two_Phase_Commit_Lock si una transacción diferente intenta modificar una clave que está bloqueada por una transacción atómica activa que está preparada. Esto puede ocurrir en uno de los dos escenarios siguientes:
  • Una transacción atómica aún se encuentra en la fase preparada y otra transacción intenta modificar una clave bloqueada por la transacción preparada. En este caso, el sistema funciona como está diseñado. Si encuentra este error, vuelva a intentar la segunda transacción. Esto es análogo a cómo las aplicaciones manejan errores de lectura fantasma o errores de control de simultaneidad de varias versiones (MVCC).
  • El valor GlobalStatus devuelto por la transacción atómica es HeuristicOutcome. En este caso, se ha cancelado una operación de transacción atómica porque ha fallado una de las operaciones de confirmación. Esta es una ocurrencia rara y puede ser necesario resolverla manualmente. Un efecto secundario de un resultado heurístico es que algunas claves se pueden dejar bloqueadas por transacciones que no se han podido confirmar o realizar un rollback. En este caso, utilice el siguiente punto final de API de REST para desbloquear la transacción atómica:
    • restproxy/api/v2/atomicTransactions/{globalTransactionId}
    Para obtener más información sobre el punto final de REST que se debe utilizar para desbloquear transacciones atómicas, consulte Desbloquear transacción atómica.

Escenario: exploración de transacciones atómicas mediante ejemplos

Considere el siguiente ejemplo, que utiliza dos de los códigos de cadenas de ejemplo que se incluyen con Oracle Blockchain Platform, Balance Transfer y Marbles. La muestra Transferencia de saldo representa a dos partes con la capacidad de transferir fondos entre saldos de cuenta. La muestra de mármoles le permite crear mármoles e intercambiarlos entre los propietarios. Puede utilizar transacciones individuales (no atómicas) para comprar un mármol mediante el intercambio de fondos en el código de cadena de transferencia de saldo y el cambio de la propiedad del mármol en el código de cadena de mármoles. Sin embargo, si se produce un error con una de esas transacciones, el libro mayor podría dejarse en un estado inconsistente: o los fondos se transfirieron, pero no el mármol o el mármol se transfiere, pero no se paga.

En este escenario, puede utilizar el código de cadenas existente con los puntos finales de la API de REST que soportan transacciones atómicas. El intercambio de fondos y la transferencia de propiedad del mármol deben tener éxito o ambos fracasan. Si una transacción encuentra un error, no se confirma ninguna transacción. Para explorar este escenario, complete los siguientes pasos:

  1. Instale las muestras Balance Transfer y Marbles en diferentes canales. Para obtener más información sobre la instalación de los ejemplos, consulte Exploración de Oracle Blockchain Platform mediante ejemplos.
  2. En la muestra Marbles, invoque la acción Create a new marble para crear una serie de mármoles para varios propietarios de mármol.
  3. Utilice el punto final de REST Invoke Atomic Transaction para completar las transacciones atómicas que llaman a los ejemplos de mármoles y transferencia de saldo.

Por ejemplo, la siguiente transacción transfiere un mármol denominado marble1 a Tom y envía 50 monedas de la cuenta a a la cuenta b.

{
 "transactions": [
   {"chaincode":"obcs-marbles","args":["transferMarble", "marble1", "tom"],"timeout":0, "channel":"goods"},
   {"chaincode":"obcs-example02","args":["invoke", "a", "b", "50"],"timeout":0, "channel":"wallet"}
 ],
 "isolationLevel": "serializable",
 "prepareTimeout": 10000,
 "sync": true
}

En la transacción anterior, si ambas transacciones se realizan correctamente en la fase de preparación, ambas transacciones se confirman en el libro mayor. Si hay un error con cualquiera de las transacciones, ninguna de ellas se confirma durante la segunda fase. En su lugar, se realiza un rollback de ambas transacciones. Por ejemplo, si hay menos de 50 monedas en la cuenta a, no se toma dinero de la cuenta y no se transfiere mármol a Tom.

Se ha producido un problema conocido con el ejemplo de mármoles y el valor por defecto del campo Propietario de mármol. Para obtener más información, consulte: Cuestiones conocidas de Oracle Blockchain Platform.