VT2018 Web3j: Difference between revisions

From air
Jump to navigation Jump to search
(Ajout documentation)
(Ajout de la section "Démonstration")
Line 42: Line 42:


= Démonstration =
= 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 [https://docs.web3j.io/command_line.html Command Line Tools] de la documentation Web3j.''

Le code source des outils de ligne de commande sont disponibles sur [https://github.com/web3j/web3j/releases/ 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 <code>web3j</code> disponible dans le dossier <code>bin/</code> :
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 :

[[File:Infuria.png | 350px]]

== 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 [https://github.com/web3j/sample-project-gradle ''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" :

<syntaxhighlight lang=Java>
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);
}
</syntaxhighlight>

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

<syntaxhighlight lang=java>
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));
}
}
}
</syntaxhighlight>

=== 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 <code>.bin</code> et un <code>.abi</code> :
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 :

[[File:FailedTransactionWeb3j.png]]


= Sources =
= Sources =

Revision as of 20:00, 9 December 2018

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

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