Protocole simplifié du Guzi

Fonctionnement général

Le fonctionnement général peut être résumé en ce petit diagramme de séquence qui déroule le processus complet de paiement entre Alice et Bob :



Explications du diagramme :


Chaque utilisateur a une blockchain personnelle qui contient l'historique de toutes les transactions auxquelles il a participé (en tant qu'acheteur et en tant que vendeur).

Quand Alice veut payer Bob, elle  ajoute la transaction quelle souhaite faire à sa blockchain puis envoie cette blockchain entière si c'est la première transaction entre Alice et Bob ou simplement la partie de sa blockchain depuis sa dernière transaction avec Bob et maintenant.

Bob vérifie plusieurs choses (surtout si c'est sa première transaction avec Alice) :

  • Est-ce qu'il fait confiance à Alice ? C'est à dire est-ce qu'il fait confiance à la personne qui s'est porté garante de la création du compte d'Alice ?
  • Est-ce que la blockchain d'Alice est valide ? Que ce soit les paiements envoyés, les Guzis créés, etc...
  • Est-ce que la transaction lui convient ?


Si tout va bien, Bob ajoute le paiement d'Alice à sa propre blockchain. Fin.

Bob ne répond pas à Alice, parce qu'un paiement envoyé est par défaut considéré comme valide. C'est pourquoi Alice l'a ajouté à sa blockchain avant même de l'envoyer.

Si Bob refuse la transaction, il envoie à Alice son refus qui l'ajoute à sa blockchain et se re-crédite les Guzis. En revanche, en cas de refus Bob n'ajoute ni la transaction, ni le refus de transaction (il n'en a pas besoin).

Si le paiement est accepté et que Bob compte 30 transactions dans le dernier block de la blockchain d'Alice, alors il signe le block (il le scelle) et l'envoi à Alice qui pourra l'ajouter à sa blockchain et entamer un nouveau block.

Sécurité contre la suppression de transaction

Dans les coulisses :

  1.  Quand Bob reçoit le paiement d'Alice accompagné de la blockchain d'Alice, il ajoute le paiement à sa blockchain, mais il ajoute également deux transactions prises au hasard de la blockchain d'Alice.
  2. Ainsi, chaque transaction se multiplie et se distribue de manière plus ou moins aléatoire. Et cela permet de faire en sorte que plusieurs personnes (sans pouvoir déterminer lesquelles à l'avance) peuvent détecter une fraude.
  3. Donc si Alice triche et supprime sa transaction puis va pour utiliser les mêmes Guzis une seconde fois envers Charles, Charles a des chances de remarquer l'absence de la transaction d'Alice s'il a récupéré "par hasard" la transaction frauduleuse chez Bob au préalable.
  4. Charles va alors refuser la transaction, blacklister Alice et envoyer à tous ses contacts la preuve de fraude (i.e les deux transactions signées par Alice contenant les mêmes Guzis).
  5. Alice est ainsi "bannie" du Guzi car elle a perdu la confiance de tous.


Il est tout à fait possible qu'Alice s'en sorte longtemps sans être repérée, bien qu'elle ne puisse plus faire de transaction avec Bob, à minima.

Format d'une transaction

Entête Json Description Détails Commentaire
v version unsigned char Version du format des données de la transaction
t type unsigned char Type de transaction
d
date timestamp Un timestamp Unix indiquant la date de la transaction
s source char[33] La clé publique de l'émetteur de la transaction.
tc target_company char[33] La clé publique de l'éventuelle entreprise cible de la transaction.
tu target_user char[33] La clé publique de l'éventuelle utilisateur cible de la transaction.
a
amount unsigned int Montant total de la transaction.
si start_index unsigned short Index du 1er Guzi de la transaction.
ei end_index unsigned short Index du dernier Guzi de la transaction.
sd start_date timestamp date du 1er Guzi de la transaction.
ed end_date timestamp date du dernier Guzi de la transaction.




w detail (what) char[] Texte libre ou spécifique selon le type de transaction.
h hash char[32] Hash signé de la transaction.


Notes :

  • Le format json est pour la lecture. Pour le stockage, le json passe par msgPack.
  • Chaque type de transaction ne contient que les champs nécessaires.

Il existe 13 types de transaction.

1/ Les Transactions de Guzis (0X)
  •     00 - Création de Guzis.
  •     01 - Création de Boites.
  •     02 - Paiement en Guzis.
  •     03 - Engagement en Guzis.
  •     04 - Engagement en Boites.
  •     05 - Refus de transaction.

2/ Les Définitions de rôles (1X)

  •     10 - Définition d'un Propriétaire d'entreprise.
  •     11 - Définition d'un Administrateur d'entreprise.
  •     12 - Définition d'un Travailleur d'entreprise.
  •     13 - Définition d'un Payeur d'entreprise.
  •     14 - Ordre de paiement.
  •     15 - Ordre de départ.

Transactions simples

Création de Guzis

Type : "00"
Description :  Cette transaction se fait par un utilisateur pour lui-même, lorsqu'il créé ses propres Guzis. Cette création ne contient donc que la date, l'identifiant de l'utilisateur et le nombre de Guzis créé.
Un utilisateur peut créer, chaque jour, ses Guzis quotidiens. Avec :

 

Format de la transaction :

{v:1, t:0, d:today, s:my_public_key, a:X, h:XXX}

Création de Boîtes

Type : "01"
Description : De la même manière que pour les Guzis, un utilisateur peut créer, chaque jour, ses Boîtes quotidiennes (autant que de Guzis).


Format de la transaction :

{v:1, t:1, d:today, s:my_public_key, a:X, h:XXX} 

Paiement en Guzis

Type : "02"
Description : C'est la transaction principale de paiement d'un utilisateur envers un autre ou envers une entreprise, ou d'une entreprise envers une autre. Quand un utilisateur reçoit un paiement :
  • Il vérifie la validité de la blockchain qui l'accompagne, si celle-ci est ok, alors...
  • Il vérifie que l'ensemble des Guzis de la transaction datent de moins d'un mois (i.e ne sont pas périmés), si ceux-ci sont ok, alors...
  • Il ajoute le montant reçu à son Total.

Format de la transaction :

{v:1, t:2, d:today, s:my_public_key, tu/tc:target_public_key, a:X, si:0, ei:12, sd:date1, ed:date3, w:detail_about_payment, h:XXX} 

Engagement en Guzis

Type : "03"
Description : Un engagement est l'équivalent de ce qu'on appelle aujourd'hui un emprunt. C'est une sorte de contrat scellé dans la blockchain qui dit "je m'engage à payer X Guzis chaque jour pendant Y jours, pour un montant total de Z".

Format de la transaction :

{v:1, t:3, d:today, s:my_public_key, tu/tc:target_public_key, a:X, si:0, ei:12, sd:date1, ed:date3, w:detail_about_payment, h:XXX}

Engagement en Boîtes

Type : "04"

Format de la transaction :

{v:1, t:4, d:today, s:my_public_key, tu/tc:target_public_key, a:X, si:0, ei:12, sd:date1, ed:date3, w:detail_about_payment, h:XXX}

Refus de transaction

Type : "05"

Description : Un utilisateur a 15 jours pour refuser une transaction, sauf s'il l'ajoute à sa blockchain, auquel cas la transaction est définitive. Quand Bob reçoit un paiement et le refuse, il n'ajoute ni la transaction reçue, ni la transaction de refus à sa blockchain. En revanche quand Alice envoie une transaction de paiement, elle l'ajoute à sa blockchain. Puis si elle reçoit le refus correspondant, elle ajoute également ce refus à sa blockchain. C'est une sécurité pour conserver une preuve de refus. Si Alice n'enregistre pas ce refus, Bob pourrait lui envoyer un refus tout en conservant les Guzis reçus sans qu'Alice ne puisse prouver que la transaction avait pourtant été annulée.

Format de la transaction :

{v:1, t:5, d:today, s:refuser_public_key, tu/tc:original_payer_public_key, a:refused_amount, w:refused_transaction_hash, h:XXX} 

Attributions de rôles d'une entreprise


Une entreprise est gérée par des utilisateurs qui peuvent avoir un ou plusieurs rôles parmi Travailleur, Propriétaire, Administrateur et Payeur. 

Travailleur

Type : "12"

Description : Les travailleurs d'une entreprise sont les utilisateur qui ont un salaire défini régulier. A une date définie de chaque mois, l'entreprise verse les salaires correspondants à chaque Travailleur.

Format de la transaction :

{v:1, t:12, d:today, s:my_public_key, tu:role_target_public_key, tc: company_public_key, a:salairy, w:any_detail, h:XXX}

Propriétaire

Type : "10"

Description : Les propriétaires d'une entreprise sont les utilisateur qui touchent les bénéfices. C'est à dire les Guzis gagnés en excès des salaires des travailleurs. A une date définie de chaque mois, l'entreprise verse ses bénéfices à ses Propriétaires au prorata des rations de chacun.

Format de la transaction 

{v:1, t:10, d:today, s:my_public_key, tu:role_target_public_key, tc: company_public_key, a:ratio, w:any_detail, h:XXX}

Administrateur

Type : "11"

Description : Les administrateurs sont les utilisateurs qui ont droit de modifier les rôles d'une entreprise.

Format de la transaction :

{v:1, t:11, d:today, s:my_public_key, tu:role_target_public_key, tc: company_public_key, w:any_detail, h:XXX}

Payeur

Type : "13"

Description : Les payeurs sont les utilisateurs qui ont droit de donner à l'entreprise des ordres de paiements envers d'autres entreprises.

Format de la transaction :

{v:1, t:13, d:today, s:my_public_key, tu:role_target_public_key, tc: company_public_key, a:max_spent, w:any_detail, h:XXX}

Note :

  • Attention, il n'y a pas de hiérarchie de droits, un administrateur n'est pas un propriétaire avec des droits supérieurs. Ce sont tous des rôles différents et un utilisateur peut se voir attribuer plusieurs de ces rôles.
  • Si une entreprise n'a pas suffisamment de Guzis pour payer ses Travailleurs, alors tous les travailleurs touchent la même somme (bien que plafonnée par leur salaire).
  • Dans ces transactions d'affectation de rôle, le champs "détails" est du texte libre qui peut préciser certaines informations pour lecture "humaine".

Ordres donnés à une entreprise

Une entreprise n'étant pas une personne physique, elle ne peut pas payer en sa personne. Il faut donc pouvoir lui envoyer des ordres de paiement pour qu'ensuite celle-ci émette le paiement correspondant. Ce système d'ordres est détaillé dans ce schéma :


Ordre de paiement

Type : "14"

Format de la transaction :

{v:1, t:14, d:today, s:order_origin_public_key, tu:company_public_key, tc: target_company_public_key, a:amount, w:any_detail, h:XXX}

Les messages retournés par l'entreprise (Company_A dans le schéma) sont des codes HTTP :

  • "403 Forbidden" : L'utilisateur n'a pas les droits de payeur.
  • "402 Payment Required" : L'entreprise n'a pas les fonds pour payer une telle somme.
  • "202 Accepted" : L'entreprise va procéder au paiement.

Ordre de départ

Type : "15"

Description : N'importe quel utilisateur peut, à tout moment, décider de quitter l'entreprise.

Format de la transaction :

{v:1, t:15, d:today, s:order_origin_public_key, tu:company_public_key, tc: target_company_public_key, a:role_leaved (10, 11, 12 or 13), w:any_detail, h:XXX} 


Notes :

  • Si le dernier administrateur de l'entreprise quitte l'entreprise, alors le propriétaire ayant le plus d'ancienneté devient administrateur.
  • S'il n'y a pas non plus de propriétaire alors le payeur ayant le plus d'ancienneté devient administrateur.
  • S'il n'y a pas non plus de payeur alors le travailleur ayant le plus d'ancienneté devient administrateur.
  • S'il n'y a pas non plus de travailleur alors le créateur de l'entreprise devient administrateur.

Format d'un Engagement (dans un block)

Un engagement est l'équivalent de ce qu'on appelle aujourd'hui un emprunt. C'est une sorte de contrat scellé dans la blockchain qui dit "je m'engage à payer X Guzis chaque jour pendant Y jours, pour un montant total de Z". Chaque block contient les différents engagements encore en cours à la date de signature du block.

Pour pouvoir s'engager dans un paiement à long terme, il y a deux conditions à respecter, uniquement pour les Guzis (les Boîtes ne sont pas concernées). Il faut donc :

  • Gagner suffisamment de Guzis, il faut donc que l'index de départ soit supérieur à 32.
  • Respecter un temps d'engagement relatif à l'âge. En respectant la formule :





Cette formule implique que l'on peut s'engager, par exemple :

  • à 18 ans : sur 10 ans,
  • à 40 ans : sur 30 ans,
  • à 70 ans : sur 4 ans,
  • à 100 ans : sur 3 semaines.

Format d'un engagement :

Entête Json Description Détails Commentaire
t
type boolean Guzi (0) ou Boite (1)
st
start_date timestamp Là date où à démarré l'engagement
ed
end_date timestamp Là date de fin de l'engagement
si
start_index unsigned short L'index du 1er Guzi/Boite de chaque jour dans l'engagement
ei
end_index unsigned short L'index du dernier Guzi/Boite de chaque jour dans l'engagement
h
hash char(32) Hash de la transaction qui a scellé l'engagement

 

Format d'un Block


Le format général d'un block est le suivant :

Entête Json Description Détails Commentaire
v version
unsigned char Version du block
d date
timestamp Un timestamp Unix indiquant la date de signature du block
ph previous_hash char[32] Le hash du block précédent.




s signer char[33] La clé publique du signataire du block.
g guzi unsigned short Nombre de Guzis résultants des transactions du block.
b boxes
unsigned short Nombre de Boites résultantes des transactions du block.




t total
unsigned int Total accumulé résultant des transactions du block




tx transactions tx[] Transactions du block
m
merkle_root
char[32]
Racine de Merkle qui hash les transactions du block
en engagements eng[] Engagements encore valides après la date de signature du block



Le hash du block prend uniquement les 8 premiers champs du block (version, date, previous_hash, signer, guzis, boxes, total et merkle_root).

Il existe 2 types de Blocks particuliers :

  • Le Block de création de compte.
  • Le Block de création d'entreprise.


Blocks de création de compte


Lors de la création d'un compte Guzi, deux blocks sont créés : un premier avec la date de naissance du nouvel utilisateur ; un second avec la clé publique du référent.

Birthday block
{v:1, d:birthday_date, ph:init_hash*, t:new_user_public_key, g:0, b:0, t:0, h:hash0}

*init_hash = "C1A551CA1C0DEEA5EFEA51B1E1DEA112ED1DEA0A5150F5E11AB1E50C1A15EED5"

Initialisation block

{v:1, d:today, ph:hash0, t:reference_public_key, g:0, b:0, t:0, h:hash1}

Détails :

  • new_user_public_key : L'identifiant du compte nouvellement créé, propriétaire de cette nouvelle blockchain.
  • reference_public_key : L'identifiant du compte qui se porte garant de la création de celui-ci.
  • hash0 : Le hash signé du block anniversaire. Signé par le nouvel utilisateur.
  • hash1 : Le hash signé du block d'initialisation. Signé par le garant.


Pour faire une demande de création de compte, un utilisateur créé son block d'anniversaire puis l'envoie à l'utilisateur qu'il veut comme référent. Celui-ci, s'il accepte, renverra la blockchain avec le block d'initialisation ajouté et signé.

Block de création d'entreprise

{v:1, d:today, ph:init_hash, t:company_public_key, g:0, b:0, t:0, tx:roles, m:merkle_root h:hash0} 

Détails :
Dans l'ensemble, c'est la même chose que pour le précédent, sauf qu'on y ajoute les rôles.

  • company_public_key : L'identifiant (la clé publique) de l'entreprise nouvellement créée.
  • roles : Les rôles dans l'entreprise. Ce sont les transactions qui définissent la situation initiale des rôles dans l'entreprise : un ou plusieurs utilisateurs Administrateurs, zéro ou plusieurs Propriétaires, zéro ou plusieurs utilisateurs Payeurs et enfin zéro ou plusieurs utilisateurs Travailleurs.


Scellement d'un block


Lorsqu'un utilisateur reçoit une transaction d'autrui, si le dernier block contenant cette transaction contient 30 (ou plus) transactions, alors il la scelle :

  1. Il vérifie que la blockchain est valide (normalement il l'a déjà fait pour accepter la transaction).
  2. Il vérifie la racine de Merkle du block.
  3. Il vérifie le hash du précédent block.
  4. Il remplie sa clé publique.
  5. Il vérifie que le nombre de guzis, de boites et que le total accumulé sont corrects.
  6. Puis il hash le block en prenant les 8 premiers champs (version, date, previous_hash, merkle_root, signer, guzis, boxes et total).
  7. Enfin il signe ce hash et l'ajoute en fin de block qu'il renvoie à son propriétaire.

Algorithmes


De la même manière que n'importe quelle cryptomonnaie, pour assurer la validité des blockchains personnelles de chaque utilisateur, deux processus sont utilisés : hashage et chiffrement.
Ainsi chaque transaction est hashée et signée.

Algorithme de chiffrement asymétrique


Pour toutes les signatures, l'algorithme utilisé est ECDSA secp256k1 (le même que bitcoin). Cela implique que :

  • Chaque clé privée fait 256 bits, soit 32 octets.
  • Chaque clé publique fait 257 bits (256 bits pour la position X + 1 bit de parité), soit 33 octets.

Algorithme de hashage

Pour les hash, l'algorithme utilisé est SHA-256. Donc les hash font 256 bits, soit 32 octets également.

Racine de Merkle


Pour calculer la racine de Merkle :

  • Il faut prendre l'ensemble des hash des transactions du block, dans leur ordre chronologique.
  • Puis y concaténer l'ensemble des hash des engagements dans leur ordre chronologique également.
  • Ensuite il faut les "hasher" 2 par 2, ce qui donne une nouvelle liste.
  • Réitérer le point 3 jusqu'à n'avoir plus qu'un seul hash. C'est la racine de Merkle.


Par exemple :

d1 = hash(a)
d2 = hash(b)
d3 = hash(c)
d4 = hash(c)            # a, b, c are 3. that's an odd number, so we take the c twice

d5 = hash(d1 concat d2)
d6 = hash(d3 concat d4)

d7 = hash(d5 concat d6)



Messages


Il y a finalement 5 types de messages qui peuvent transiter :

  1. Une transaction classique accompagnée de sa blockchain. Son titre est "Transaction" et son contenu un fichier .guzi qui contient toute la blockchain de l'utilisateur.
  2. Un block unique (qui aurait été scellé). Son titre est "Block" et son contenu un fichier .gbk (Guzi block) qui contient le block.
  3. Une transaction seule (pour les ordres d'entreprise ou les refus par exemple). Son titre est "Transaction" et son contenu un fichier .gtx (Guzi transaction) qui contient la transaction uniquement.
  4. Une demande (de signature ou de référent pour une création de compte). Son titre est "Request" et son contenu un fichier .guzi avec la blockchain de l'utilisateur.
  5. Un message (refus ou validation d'ordre d'une entreprise). Son titre est "Message" et son contenu du texte simple.

Commentaires