Effectuer des mises à jour atomiques entre les codes chaîne et les canaux

Vous pouvez utiliser des transactions atomiques pour effectuer plusieurs transactions sur les canaux et les codes chaîne de manière atomique.

Une transaction atomique est une série indivisible d'opérations de données qui réussissent toutes ou aucune ne réussissent.

Les transactions atomiques peuvent être utiles dans des situations complexes où plusieurs codes chaîne sont déployés sur des canaux distincts. Vous pouvez utiliser des transactions atomiques pour maintenir la cohérence des données lors de l'exécution de plusieurs transactions blockchain, même en cas de défaillance du réseau ou du système. Oracle Blockchain Platform prend en charge les transactions atomiques à l'aide du protocole de validation en deux phases, où une phase initiale dans laquelle chaque opération de données est préparée est suivie d'une phase dans laquelle chaque opération de données est réellement validée.

Les transactions atomiques fonctionnent au niveau de l'application. En règle générale, vous n'avez pas besoin de modifier la logique de code chaîne existante pour prendre en charge les transactions atomiques. Etant donné qu'un ou plusieurs arguments supplémentaires sont ajoutés par la structure de transactions atomiques, assurez-vous que tout code chaîne existant n'effectue pas de vérifications strictes du nombre d'arguments transmis dans la méthode de code chaîne. Les transactions atomiques sont prises en charge par l'adresse d'API REST suivante :
  • restproxy/api/v2/atomicTransactions
L'adresse d'API REST prépare les transactions conformément à la définition de votre code chaîne, puis utilise les fonctions de code chaîne intégrées pour valider (commit) toutes les transactions ou annuler (rollback) toutes les transactions en cas d'erreur lors de la phase de préparation. Pour plus d'informations sur les adresses REST à utiliser pour implémenter des transactions atomiques, reportez-vous à Adresses REST de transactions atomiques.

Chaque transaction atomique est composée de deux transactions blockchain ou plus. Le résultat (valeur returnCode) de la transaction atomique est Success ou Failure. Dans une transaction atomique, chaque transaction de chaîne de blocs demandée est divisée en deux opérations distinctes : une phase de préparation, puis une phase de validation (commit) ou une phase d'annulation (rollback).

  • Au cours de la phase de préparation, chaque transaction est approuvée comme d'habitude, mais au lieu d'être finalisée, les modifications sont préparées et les valeurs sont verrouillées pour empêcher les autres transactions de modifier les valeurs préparées.
  • Si la phase de préparation réussit pour chaque transaction de chaîne de blocs, les transactions sont approuvées et validées à l'aide du code chaîne intégré. Les valeurs verrouillées précédemment sont déverrouillées et le résultat de la transaction atomique est Success.
  • Si la phase de préparation échoue pour une transaction de chaîne de blocs, toutes les autres transactions pour lesquelles la phase de préparation a réussi sont annulées (rollback), à l'aide du code chaîne intégré. Les modifications en transfert sont supprimées et les valeurs verrouillées précédemment sont déverrouillées. Le résultat de la transaction atomique est Failure.
Etant donné que les transactions atomiques fonctionnent par verrouillage des clés, vous pouvez recevoir une erreur Two_Phase_Commit_Lock si une autre transaction tente de modifier une clé verrouillée par une transaction atomique actuellement active préparée. Cela peut se produire dans l'un des deux scénarios suivants :
  • Une transaction atomique est toujours en phase de préparation et une autre transaction tente de modifier une clé verrouillée par la transaction préparée. Dans ce cas, le système fonctionne comme prévu. Si vous rencontrez cette erreur, réessayez la deuxième transaction. Cela est analogue à la façon dont les applications gèrent les erreurs de lecture fantôme ou les erreurs MVCC (Multi-version Concurrency Control).
  • La valeur GlobalStatus renvoyée par la transaction atomique est HeuristicOutcome. Dans ce cas, une opération de transaction atomique a été annulée car l'une des opérations de validation a échoué. Il s'agit d'une occurrence rare qui peut nécessiter une résolution manuelle. Un effet secondaire d'un résultat heuristique est que certaines clés peuvent être laissées verrouillées par des transactions qui n'ont pas pu être validées ou annulées. Dans ce cas, utilisez l'adresse d'API REST suivante pour déverrouiller la transaction atomique :
    • restproxy/api/v2/atomicTransactions/{globalTransactionId}
    Pour plus d'informations sur l'adresse REST à utiliser pour déverrouiller les transactions atomiques, reportez-vous à Déverrouiller la transaction atomique.

Scénario : Explorer les transactions atomiques à l'aide d'échantillons

Prenons l'exemple suivant, qui utilise deux exemples de code chaîne inclus avec Oracle Blockchain Platform, le transfert de solde et les billes. L'échantillon Transfert de solde représente deux parties pouvant transférer des fonds entre des soldes de compte. L'échantillon Marbles vous permet de créer des billes et de les échanger entre les propriétaires. Vous pouvez utiliser des transactions individuelles (non atomiques) pour acheter un marbre en échangeant des fonds dans le code chaîne de transfert de solde et en changeant la propriété du marbre dans le code chaîne Marbles. Cependant, si une erreur se produit avec l'une de ces transactions, le livre peut être laissé dans un état incohérent : soit les fonds ont été transférés, mais pas le marbre ou le marbre est transféré mais non payé.

Dans ce scénario, vous pouvez utiliser le code chaîne existant avec les adresses d'API REST qui prennent en charge les transactions atomiques. L'échange de fonds et le transfert de propriété du marbre doivent tous deux réussir ou les deux échouer. Si l'une des transactions rencontre une erreur, aucune des transactions n'est validée. Pour explorer ce scénario, procédez comme suit :

  1. Installez les échantillons de transfert de solde et de billes sur différents canaux. Pour plus d'informations sur l'installation des échantillons, reportez-vous à Exploration d'Oracle Blockchain Platform à l'aide d'échantillons.
  2. Dans l'exemple Marbles, appelez l'action Create a new marble pour créer un certain nombre de marbres pour différents propriétaires de marbre.
  3. Utilisez l'adresse REST Invoke Atomic Transaction pour terminer les transactions atomiques qui appellent les échantillons Marbles et Transfert de solde.

Par exemple, la transaction suivante transfère une bille nommée marble1 à Tom et envoie 50 pièces du compte a au compte 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
}

Dans la transaction précédente, si les deux transactions réussissent dans la phase de préparation, les deux transactions sont validées dans le livre. En cas d'erreur avec l'une ou l'autre transaction, aucune transaction n'est validée au cours de la deuxième phase. Au lieu de cela, les deux transactions sont annulées. Par exemple, s'il y a moins de 50 pièces dans le compte a, aucun argent n'est prélevé sur le compte et aucun marbre n'est transféré à Tom.

Il existe un problème connu avec l'exemple Marbles et la valeur par défaut du champ Propriétaire de marbre. Pour plus d'informations, reportez-vous à Problèmes connus pour Oracle Blockchain Platform.