Realizar actualizaciones atómicas en cadenas y canales

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

Una transacción atómica es una serie indivisible de operaciones de datos que todas tienen éxito o ninguna tiene éxito.

Las transacciones atómicas pueden ser útiles en situaciones complejas en las que se despliegan varios códigos de cadenas en canales separados. Puede utilizar transacciones atómicas para mantener la coherencia de los datos mientras ejecuta varias transacciones de cadena de bloques, incluso si se produce un fallo de 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 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 cadenas existente no realice comprobaciones estrictas del número de argumentos transferidos en el método de código de cadenas. 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 realizar un rollback de todas las transacciones si hay algún error durante la fase de preparación. Para obtener más información sobre los puntos finales de REST que se utilizarán 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 ubicados temporalmente.
  • Si la fase de preparación es correcta para cada transacción de cadena de bloques, las transacciones se endosan y confirman mediante el uso de un 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 blockchain, se realiza un rollback de todas las demás transacciones en las que la fase de preparación se realizó correctamente, nuevamente 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 mediante el bloqueo de 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 está en la fase de preparación 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 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 canceló una operación de transacción atómica porque falló una de las operaciones de confirmación. Esto es poco frecuente 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 han confirmado o realizado 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 utilizará para desbloquear transacciones atómicas, consulte Desbloqueo de transacciones atómicas.

Escenario: Exploración de transacciones atómicas mediante muestras

Considere el siguiente ejemplo, que utiliza dos de los códigos de cadenas de ejemplo que se incluyen con Oracle Blockchain Platform, transferencia de saldo y mármoles. La muestra Transferencia de saldo representa a dos partes con capacidad para transferir fondos entre saldos de cuenta. La muestra Mármoles le 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 Balance Transfer y el cambio de la propiedad del mármol en el código de cadena Marbles. Sin embargo, si se produce un error con una de esas transacciones, el libro mayor podría quedar en un estado inconsistente: 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 soportan transacciones atómicas. El intercambio de fondos y la transferencia de la 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 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 Exploración de Oracle Blockchain Platform mediante ejemplos.
  2. En el ejemplo Marbles, llame a 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 mármoles y a los ejemplos de transferencia de saldo.

Por ejemplo, la siguiente transacción transfiere un mármol denominado marble1 a Tom y envía 50 monedas desde 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.

Hay un problema conocido con la muestra Mármoles y el valor predeterminado del campo Propietario de mármol. Para obtener más información, consulte: Problemas conocidos de Oracle Blockchain Platform.