VT2018 Web3j

From air
Revision as of 22:57, 9 December 2018 by Enzo.Molion (talk | contribs) (Ajout des sous-sections de "Synthèse")
Jump to navigation Jump to search
Logo Web3j

Auteur

  • Nom : MOLION Enzo
  • Mail : enzo.molion.0@gmail.com
  • Sujet : Web3j

Résumé

Web3j se présente sur son site web comme "Une librairie légère, réactive, à typage sûr pour Android, Java, Kotlin et Scala pour connecter des applications JVM à la chaîne de blocs Ethereum".

Cette technologie pallie à un problème majeur d'Ethereum : comment faciliter aux communautés Java, Kotlin, Scala, etc. l'accès à la technologie d'avenir qu'est la chaîne de blocs ? Que ce soit sa prise en main ou son utilisation intensive, Web3j promet de simplifier la vie du programmeur souhaitant manipuler cette technologie.

Cette page se propose d'apporter une première approche de Web3j et donc d'exposer succinctement le principe de la chaîne de blocs puis plus en détails Ethereum et enfin permettra au lecteur d'approcher Web3j par l'exemple, via une démonstration.

Il est ici notifié au lecteur que cette page ne constitue qu'une page de synthèse de la technologie et doit être adossée à la présentation et à la séance de question réponses réalisées à Polytech Grenoble en amphithéâtre 007 le 10 décembre 2018 aux alentours de 17h.

Mots clés

  • Chaine de blocs
  • Ethereum
  • API/librairie
  • Java

Abstract

Web3j introduces itself (on its website) as follows : "Connect JVM applications to Ethereum blockchains with web3j - a lightweight, reactive, type safe library for Java, Android, Kotlin and Scala".

This technology overcomes the gap that goes from Java, Kotlin, Scala, etc. communities to the Ethereum blockchain. Indeed, blockchains seem to be an important part of IT's future and its acces to developers has to be as easy as possible. Web3j promises to answer this tough topic both via its handyness and completeness.

On this page, the reader shall find an overview of Web3j, thus an small introduction to the blockchain principles, followed by a more thorough explanation of Ethereum working principles and at last a demonstration of a use case of Web3j.

This page oughts to present an overview of the discussed technologies and forms a whole only with the dedicated presentation and questions/answers session at Polytech Grenoble, lecture hall 007 on december 10th, 2018 around 5PM.

The rest of the page is in English but a non-french reader might want to take a look at the references ("Sources" section) which are in English.

Keywords

  • Blockchain
  • Ethereum
  • API/library
  • Java

Synthèse

Le sujet proposé est ici "Web3j". Il s'agit d'une librairie Android, Java, Kotlin et Scala pour connecter des applications à la chaîne de blocs Ethereum.

Cependant, cette fiche de synthèse étant rédigée dans le cadre de l'enseignement Veille Technologique et Stratégique de RICM5 à Polytech Grenoble, il convient ici de vulgariser au maximum ce sujet.

Ainsi, construiront notre synthèses par couches conceptuelles successives : Web3j étant une librairie pour Ethereum, celle-ci étant une chaîne de blocs, nous commencerons par rapidement expliquer ce que recouvre ce terme très en vogue, puis nous détaillerons le principe d'Ethereum avant de donner les bases nécessaires concernant la librairie Web3j à la compréhension de l'application que constitue la démonstration.

La chaine de blocs

Représentation schématique d'une portion de chaîne de blocs

Une chaîne de blocs est une structure de données permettant de stocker des transactions (de types divers), assurant avant tout deux propriétés principales. Elle est :

  • immuable,
  • décentralisée.

Sa décentralisation est son principal intérêt : il s'agit de pouvoir enregistrer lesdites transactions sans intermédiaire de confiance, les utilisateur de la chaîne de blocs assurant son intégrité de par la décentralisation, justement. Chacun possède une copie de la chaîne de blocs et peut participer à sa croissance.

C'est ici qu'intervient l'aspect immuable : une fois une transaction inscrite dans la chaîne de blocs, celle-ci y est demeure irrémédiablement. Les différents utilisateurs participent à la croissance de la manière suivante : lorsque un utilisateur veut stocker une donnée dans celle-ci, il en fait la demande. Des demandes concurrentes arrivent donc à tous les utilisateurs qui doivent donc former un consensus sur l'ordre des transactions à ajouter à la structure de données afin que celle-ci reste intègre malgré son aspect distribué. Le mécanisme de consensus est un grand enjeu de la recherche actuelle concernant la chaîne de blocs (deux de ces mécanismes seront évoqués dans la section dédiée à Ethereum).

Ainsi, une chaîne de blocs n'est qu'une structure de données particulière (distribuée et immuable) et n'est pas nécessairement liée à une crypto-monnaie ou publique. Ceci relève de l'utilisation faite de celle-ci, comme dans le cas de Bitcoin (application de chaîne de blocs la plus populaire actuellement) ou bien, dans notre cas, d'Ethereum.


Ethereum

Ethereum est un protocole de gestion de contrats intelligents stockés dans une chaîne de blocs et utilisant une cryptomonnaie : l’éther.

Un contrat intelligent est le nom donné à un ensemble composé de code informatique, de données liées à celui-ci pour son exécution et ayant une adresse dans la chaîne de blocs.

Le principe consiste donc à stocker du code dans la chaîne de blocs afin de permettre aux utilisateurs de celle-ci de l'exécuter. L'éther ne sert qu'à rétribuer les utilisateurs d'Ethereum puisque ce sont eux qui fournissent l'infrastructure nécessaire à sa bonne marche. Il est nécessaire à quelqu'un souhaitant déployer du code sur celle-ci et permettre son execution. Il permet également de rétribuer les utilisateurs participant au mécanisme de consensus.


Web3j

Web3j est une librairie facilitant l'utilisation d'Ethereum, notamment en permettant à des développeurs de langages répandus mais n'ayant pas de lien avec Ethereum (Android, Java, Scala pour ne citer que les principaux) de prendre en main celle-ci facilement.

Le principe est le suivant : le développeur code un contrat intelligent dans le langage d'Ethereum (Solidity) puis le compile (en .bin et .abi). Ensuite, il utilise le code généré afin de permettre à Web3j de générer les objets correspondants dans le langage de son choix pour pouvoir les utiliser en programmation orientée objet dans la JVM. Le code qui sera déployé sur la chaîne de blocs sera bien celui écrit en solidity mais la manipulation des objets et données en résultant se fera via le langage choisi par le développeur.

SchemaWeb3j.png

Ainsi (et comme illustré dans le schéma ci-dessus), Web3j facilite l'utilisation de la chaîne de blocs Ethereum :

  • Transfert d'ether,
  • Création de contrat,
  • Transaction sur un contrat,
  • Détails sur des transactions (quel qu'en soit l'instigateur).

Beaucoup de choses sont simplifiées : la gestion du chiffrement, du porte-feuilles Ethereum, la gestion de la synchronisation (Web3j permet de gérer chacune des manipulations de manière synchrone ou asynchrone),...

Routine de développeur

Il est dans un premier temps nécessaire de créer un porte-feuilles Ethereum. Cette procédure ne se réalise qu'une seule fois et permet d'avoir porte-feuilles électronique permettant la gestion d'éther et de contrats intelligents Ethereum. Un outil en ligne de commande est mis à disposition par Web3j afin de faciliter sa manipulation.

Afin de s'ouvrir une porte vers la chaîne de blocs Ethereum, il est nécessaire de créer un client Ethereum, celui-ci fait office d'ouverture sur la chaîne de blocs en propageant les instructions de l'utilisateur au reste de la chaîne de blocs.

Une fois la communication avec la chaîne de blocs mise en place via le client, l'utilisateur code un contrat intelligent en Solidity, le compile et souhaite donc le déployer sur la chaîne de blocs. Pour ce faire, il doit bénéficier de suffisamment d'ether pour payer le coût de la transaction.

Lorsque l'utilisateur a compilé son code Solidity, il souhaite utiliser son langage favoris pour manipuler Ethereum (ou plus souvent intégrer de la manipulation d'Ethereum à un programme, codé dans son langage favori). Pour ce faire, il utilise Web3j afin de générer les objets interprétables par la JVM correspondants (à ceux de Solidity). Une fois ceci fait, il peut coder son application manipulant Ethereum à l'aide de son langage favori.

Démonstration

La démonstration donnée ici se base sur un exemple fourni par Web3j sur son GitHub (voir sources) et destinée à un déploiement via Gradle.

Elle consiste à procéder aux étapes suivantes :

  • installation des outils de ligne de commande web3j
  • création d'un porte-feuilles Ethereum
  • codage et déploiement d'un contrat intelligent sur la chaine de blocs

On remarque ici que du fait que l'auteur n'ait souhaité engagé des frais, cette démonstration s'avère dans son cas incomplète : le déploiement sur la chaine de blocs n'est pas effectif par défaut d'Ether dans le porte-feuilles.

Installation des outils de ligne de commande web3j

Cette section est largement inspirée de l'article Command Line Tools de la documentation Web3j.

Le code source des outils de ligne de commande sont disponibles sur la page GitHub du projet Web3j.

Il convient de les télécharger et les décompresser à l'endroit de son choix, avant de pouvoir utiliser le fichier binaire web3j disponible dans le dossier bin/ :

unzip web3j-<version>.zip
./web3j-<version>/bin/web3j

Création d'un porte-feuilles Ethereum

L'installation des outils de ligne de commande web3j permettent de créer très facilement un porte-feuilles web3j :

web3j wallet create

Il est cependant important de conserver son mot de passe précieusement : sans celui-ci, impossible de d'utiliser son Ether...

Utilisation d'un client Ethereum Infuria

Afin de ne pas perdre le lecteur dans des considérations complexes consernant la création et la gestion d'un client Ethereum local, nous proposons ici d'utiliser un client déjà créé et disponible sur le service dédié en ligne Infuria. Il suffit de se rendre sur la page du service en question, de créer un compte et de se laisser guider par les instructions données.

On obtient un client Ethereum utilisable :

Infuria.png

Codage et déploiement d'un contrat intelligent sur la chaine de blocs

Nous ne codons pas ici de contrat intelligent de A à Z mais reprenons les principaux éléments de celle donnée sur la page Sample Project Gradle du dép GitHub de Web3j.

Codage

On présente d'abord le contrat intelligent dans le langage Solidity, contrat basique relevant du "Hello Ethereum World" :

pragma solidity ^0.5.0;

contract Mortal {
    /* Define variable owner of the type address*/
    address payable owner;

    /* this function is executed at initialization and sets the owner of the contract */
    constructor () public { owner = msg.sender; }

    /* Function to recover the funds on the contract */
    function kill() public { if (msg.sender == owner) selfdestruct(owner); }
}

contract Greeter is Mortal {

    /* define variable greeting of the type string */
    string greeting;

    /* this runs when the contract is executed */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }

    function newGreeting(string memory _greeting) public {
        emit Modified(greeting, _greeting, greeting, _greeting);
        greeting = _greeting;
    }

    /* main function */
    function greet() public returns (string memory)  {
        return greeting;
    }
 
    /* we include indexed events to demonstrate the difference that can be
    captured versus non-indexed */
    event Modified(
            string indexed oldGreetingIdx, string indexed newGreetingIdx,
            string oldGreeting, string newGreeting);
}

On présente maintenant la classe Application et notamment la méthode run de celle-ci. En effet, il s'agit du le code déployé sur la chaîne de blocs.

public class Application {

        private static final Logger log = LoggerFactory.getLogger(Application.class);

        public static void main(String[] args) throws Exception {
                new Application().run();
        }

        private void run() throws Exception {

                // We start by creating a new web3j instance to connect to remote nodes on the
                // network.
                // DONE: Enter your Infura token here;
                Web3j web3j = Web3j.build(
                                new HttpService("https://rinkeby.infura.io/v3/18b8d86a9ccf4ef387648152576d6e02"));
                log.info("Connected to Ethereum client version: "
                                + web3j.web3ClientVersion().send().getWeb3ClientVersion());

                // We then need to load our Ethereum wallet file
                // DONE: Generate a new wallet file using the web3j command line tools
                Credentials credentials = WalletUtils.loadCredentials("VTdemo",
                                "/home/enzo/Documents/RICM5/S9/VT/wallet.json");
                log.info("Credentials loaded");

                // FIXME: Get some ether
                log.info("Sending 1 Wei (" + Convert.fromWei("1", Convert.Unit.ETHER).toPlainString() + " Ether)");
                TransactionReceipt transferReceipt = Transfer
                                .sendFunds(web3j, credentials, "0x19e03255f667bdfd50a32722df860b1eeaf4d635",
                                                BigDecimal.ONE, Convert.Unit.WEI) // 1 wei = 10^-18 Ether
                                .send();
                log.info("Transaction complete, view it at https://rinkeby.etherscan.io/tx/"
                                + transferReceipt.getTransactionHash());

                // Now lets deploy a smart contract
                log.info("Deploying smart contract");
                ContractGasProvider contractGasProvider = new DefaultGasProvider();
                Greeter contract = Greeter.deploy(web3j, credentials, contractGasProvider, "test").send();

                String contractAddress = contract.getContractAddress();
                log.info("Smart contract deployed to address " + contractAddress);
                log.info("View contract at https://rinkeby.etherscan.io/address/" + contractAddress);

                log.info("Value stored in remote smart contract: " + contract.greet().send());

                // Lets modify the value in our smart contract
                TransactionReceipt transactionReceipt = contract.newGreeting("Test pour la demonstration de VT").send();

                log.info("New value stored in remote smart contract: " + contract.greet().send());

                for (Greeter.ModifiedEventResponse event : contract.getModifiedEvents(transactionReceipt)) {
                        log.info("Modify event fired, previous value: " + event.oldGreeting + ", new value: "
                                        + event.newGreeting);
                        log.info("Indexed event previous value: " + Numeric.toHexString(event.oldGreetingIdx)
                                        + ", new value: " + Numeric.toHexString(event.newGreetingIdx));
                }
        }
}

Déploiement

Il convient, pour pouvoir coder l'application Java d'avoir généré le code Java du Greeter depuis Solidity. Une fois de plus, on utilise les outils de ligne de commande Web3j, voici comment procéder :

  • On compile le fichier solidity vers un .bin et un .abi :
solc src/main/solidity/greeter/Greeter.sol --bin --abi --optimize -o build/ --overwrite
  • Puis on génère le code Java :
./web3j solidity generate -b build/Greeter.bin -a build/Greeter.abi -p org.<your>.<packagename>.generated -o src/main/java/

Enfin, on peut déployer ce code vers la chaîne de blocs grâce à l'outil de construction gradle :

 ./gradlew && ./gradlew build

Résultat

Comme mentionné plus haut, le résultat n'est ici pas concluant par manque d'Ether.

On constate cela en lisant les logs de déploiement :

FailedTransactionWeb3j.png

Sources