Ce programme a été écrit en ocaml 4.10.0.
Ces packages tiers sont requis pour compiler le programme.
zarith
opam install zarith
hex
opam install hex
Dans le terminal: make
./miner -p xxxx [--ri "xxx.xxx.xxx.xxx" --rp xxxx] [-d x]
Où
Exemple, pour le premier mineur:
./miner -p 8000
Le second:
./miner -p 8001 --ri "127.0.0.1" --rp 8000
Le mineur n'a pas de commande d'interaction.
`./wallet -p xxxx -n %s [-i "xxx.xxx.xxx.xxx]"
Où
Exemple:
`./wallet -p 8001 -i "127.0.0.1 -n SuperWallet"
Ouvrir un wallet donne ce résultat:
La commande help
réaffiche les commandes possibles.
La commande 1
permet d'afficher les noeuds du réseau (seulement les mineurs).
On voit les deux noeuds du réseau.
La commande 2
permet d'envoyer une transaction au mineur distant. Cette transaction sera partagée aux autres mineurs
et un nouveau bloc sera créé pour accueillir cette transaction.
La transaction est envoyée au Mineur 8000 qui l'a partagé au mineur 8001. Les deux se mettent à miner.
Le destinataire de la transaction n'a pas besoin d'être un utilisateur réel (pas d'authentification).
Lorsque les mineurs minent des blocs, ils n'envoient pas les nouveaux blocs aux wallets. Un wallet reçoit la blockchain à sa première connexion au mineur ou avec cette commande explicite:
Dans cet exemple, on a repris la transaction précédente. Le mineur 8001 avait trouvé le bloc en premier et l'a partagé au mineur 8000 qui l'a accepté. Le wallet refresh la blockchain et reçoit les nouveaux headers (le wallet ne stocke pas les transactions).
Pour confirmer qu'une transaction est contenu dans un bloc. L'utilisateur passe par la commande 4
.
Le logiciel demande à l'utilisateur le hash de la transaction à valider.
L'utilisateur a demandé la preuve de la transaction de hash f7630f2637585a78d2943abbe313c99e. Le mineur 8000 a trouvé cette transaction dans le bloc 1 et crée la preuve de merkle qu'il envoie au wallet. Le wallet reçoit une preuve associée au bloc 1 qu'il possède. Il vérifie alors la preuve et affiche le succès de celle-ci.
Plusieurs situations peuvent arriver:
Dans ce cas le wallet est simplement averti:
Dans la commande de confirmation de transaction, le wallet refresh automatiquement sa blockchain de headers dans le cas où le bloc associé à une preuve est inexistant dans sa mémoire. L'opération est alors transparente pour l'utilisateur.
Si le wallet est trop rapide dans sa demande, alors il reçoit un message d'attente.
1) Blockchain concurrente
Notre blockchain ne gère pas le problème des blockchains concurrentes pour la raison suivante : A cause de notre implémentation du système d'envoi/réception des messages entre les mineurs, un mineur ne sait pas qui lui parle. Ceci est dû au fait que l'adresse ip/port d'un mineur lorsqu'il envoie un message en mode client n'est pas son adresse d'écoute. Ainsi, lorsqu'un mineur reçoit un bloc dont l'id est supérieur à mon_id_courant + 1, il ne peut pas demander la blockchain entière au mineur spécifique qui lui a envoyé le bloc. Une manière de résoudre ce problème aurait été d'ajouter une interface à tout message de la forme : { type_node : Miner/Wallet, le type de noeud du client addr_listen : sockaddr, l'ip/port d'écoute du client message : message, l'objet de type 'message' qui représente l'objet ou la question transmis } Avec cette interface, le mineur qui reçoit un bloc d'une chaine concurrente avancée aurait pu demander au mineur dont l'ip/port est transmis dans le message la blockchain entière.
2) Réseau
Nous avions tenté de lancer le programme sur plusieurs machines séparées. La logique du programme est censée autoriser ceci. Cependant nous n'avons pas réussi à faire fonctionner une communication TCP entre deux programmes Ocaml. En particulier les messages sont bien transmis entre les machines, mais la communication est bloquée (comme un blocage pare-feu, mais a priori ceci était censé être autorisé). Après de nombreux essais sans succès, il a été décidé de ne pas poursuivre. Le programme ne fonctionne donc qu'en local.