Effectuer des mises à jour atomiques sur des codes de chaîne et des canaux

Vous pouvez utiliser des transactions atomiques pour effectuer plusieurs transactions sur des canaux et des codes de 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.

Les transactions atomiques peuvent être utiles dans des situations complexes où plusieurs codes de chaîne sont déployés dans 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 de chaîne de blocs, même en cas de défaillance du réseau ou du système. Oracle Blockchain Platform prend en charge les transactions atomiques en utilisant le protocole de validation en deux phases, où une phase initiale où chaque opération de données est préparée est suivie d'une phase où chaque opération de données est réellement validée.

Les transactions atomiques fonctionnent au niveau de l'application. En général, il n'est pas nécessaire de modifier la logique du code de chaîne existante pour prendre en charge les transactions atomiques. Comme un ou plusieurs arguments supplémentaires sont ajoutés par le cadre de transactions atomiques, assurez-vous que tout code de chaîne existant n'effectue pas de vérifications strictes sur le nombre d'arguments transmis dans la méthode de code de chaîne. Les transactions atomiques sont prises en charge par le point d'extrémité d'API REST suivant :
  • restproxy/api/v2/atomicTransactions
Le point d'extrémité de l'API REST prépare les transactions comme défini par votre code de chaîne, puis utilise les fonctions de code de chaîne intégrées pour valider toutes les transactions, ou pour annuler toutes les transactions en cas d'erreur lors de la phase de préparation. Pour plus d'informations sur les points d'extrémité REST à utiliser pour mettre en oeuvre des transactions atomiques, voir Points d'extrémité 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 ou d'annulation.

  • Au cours de la phase de préparation, chaque transaction est endossée comme d'habitude, mais au lieu d'être finalisée, les modifications sont inscrites dans une table intermédiaire et les valeurs sont verrouillées pour empêcher d'autres transactions de modifier les valeurs inscrites dans la table intermédiaire.
  • Si la phase de préparation aboutit pour chaque transaction de chaîne de blocs, les transactions sont endossées et validées à l'aide du code de chaîne intégré. Les valeurs précédemment verrouillées 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 repositionnées, encore une fois à l'aide du code de chaîne intégré. Les modifications en zone de préparation sont supprimées et les valeurs précédemment verrouillées sont déverrouillées. Le résultat de la transaction atomique est Failure.
Comme les transactions atomiques fonctionnent par des clés de verrouillage, vous pouvez recevoir une erreur Two_Phase_Commit_Lock si une autre transaction tente de modifier une clé qui est verrouillée par une transaction atomique actuellement active qui est préparée. Cela peut se produire dans l'un des deux scénarios suivants :
  • Une transaction atomique est encore dans la phase préparée, et une autre transaction tente de modifier une clé qui a été 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. Ceci est analogue à la façon dont les applications gèrent les erreurs de lecture fantôme ou les erreurs de contrôle de simultanéité de versions (MVCC).
  • La valeur GlobalStatus retournée par la transaction atomique est HeuristicOutcome. Dans ce cas, une opération de transaction atomique a été annulée en raison de l'échec de l'une des opérations de validation. Il s'agit d'un événement 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 le point d'extrémité d'API REST suivant pour déverrouiller la transaction atomique :
    • restproxy/api/v2/atomicTransactions/{globalTransactionId}
    Pour plus d'informations sur le point d'extrémité REST à utiliser pour déverrouiller des transactions atomiques, voir Déverrouiller une transaction atomique.

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

Prenons l'exemple suivant, qui utilise deux exemples de code de chaîne inclus avec Oracle Blockchain Platform, Balance Transfer et Marbres. L'exemple de transfert de solde représente deux parties qui peuvent transférer des fonds entre des soldes de compte. L'échantillon Marbres vous permet de créer des marbres et de les échanger entre propriétaires. Vous pouvez utiliser des transactions individuelles (non atomiques) pour acheter un marbre en échangeant des fonds dans le code de chaîne de transfert de solde et en modifiant la propriété du marbre dans le code de chaîne de billes. Cependant, si une erreur se produit avec l'une de ces transactions, le grand 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 pas payé.

Dans ce scénario, vous pouvez utiliser le code de chaîne existant avec les points d'extrémité 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 échouer. Si l'une ou l'autre des transactions rencontre une erreur, aucune transaction n'est validée. Pour explorer ce scénario, procédez comme suit :

  1. Installez les échantillons Balance Transfer et Marbles sur différents canaux. Pour plus d'informations sur l'installation des échantillons, voir Explorer Oracle Blockchain Platform à l'aide d'échantillons.
  2. Dans l'exemple Marbres, appelez l'action Create a new marble pour créer un certain nombre de marbres pour différents propriétaires de marbre.
  3. Utilisez le point d'extrémité REST Invoke Atomic Transaction pour effectuer des transactions atomiques qui appellent à la fois les échantillons Marbres et Transfert de solde.

Par exemple, la transaction suivante transfère un marbre nommé 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 à la phase de préparation, les deux transactions sont validées dans le grand livre. S'il y a une erreur dans 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 repositionné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.