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

Puede utilizar transacciones atómicas para completar varias transacciones en los distintos canales y códigos de cadenas de forma atómica.

Una transacción atómica es una serie indivisible de operaciones de datos que son todas correctas o ninguna.

Las transacciones atómicas pueden ser útiles en situaciones complejas en las que se despliegan varios códigos de cadena en canales separados. Puede utilizar transacciones atómicas para mantener la consistencia de los datos mientras ejecuta varias transacciones de blockchain, 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 en el nivel de aplicación. Normalmente, no es necesario cambiar la lógica de código de cadena 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 su código de cadena y, a continuación, utiliza funciones de código de cadena 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 blockchain. El resultado (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 aprueba como de costumbre, pero en lugar de finalizarla, 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 se realiza correctamente para cada transacción de blockchain, las transacciones se endosan y confirman mediante el uso del código de cadena 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, nuevamente mediante el uso del código de cadena incorporado. Los cambios temporales 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 mediante el bloqueo de claves, es posible que reciba un error Two_Phase_Commit_Lock si una transacción diferente intenta modificar una clave 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 una transacción diferente intenta modificar una clave bloqueada por la transacción preparada. En este caso, el sistema funciona según lo diseñado. Si encuentra este error, vuelva a intentar la segunda transacción. Esto es análogo a cómo las aplicaciones manejan los errores de lectura fantasma o los 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 una de las operaciones de confirmación ha fallado. Esto es raro y puede que sea necesario resolverlo manualmente. Un efecto secundario de un resultado heurístico es que algunas claves pueden quedar bloqueadas por transacciones que no se pudieron confirmar o revertir. 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 muestras

Tenga en cuenta el siguiente ejemplo, que utiliza dos de los códigos de cadena de ejemplo que se incluyen con Oracle Blockchain Platform, Balance Transfer y Marbles. La muestra Transferencia de saldo representa dos partes con la capacidad de transferir fondos entre saldos de cuenta. La muestra Mármoles te permite crear mármoles e intercambiarlos entre propietarios. Puede utilizar transacciones individuales (no atómicas) para comprar un mármol mediante el intercambio de fondos en el código de cadena Transferencia de saldo y el cambio de la propiedad del mármol en el código de cadena Mármol. Sin embargo, si se produce un error con una de esas transacciones, el libro mayor podría dejarse en un estado incoherente: o bien 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 cadena existente con los puntos finales de la API de REST que admiten transacciones atómicas. El intercambio de fondos y la transferencia de la propiedad del mármol deben tener éxito o ambos fracasan. Si alguna de las transacciones encuentra un error, ninguna de las transacciones se confirma. Para explorar este escenario, complete los pasos siguientes:

  1. Instale las muestras de transferencia de saldo y mármoles en diferentes canales. Para obtener más información sobre la instalación de los ejemplos, consulte Explore Oracle Blockchain Platform Using Samples.
  2. En la muestra Mármoles, 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 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.