[JAVA] Envoyer des transactions signées à l'aide de Web3j

Contenu de l'article

Comment envoyer une transaction signée à l'aide de la bibliothèque Java d'Ethereum "Web3j"

environnement

la mise en oeuvre

C'est assez difficile car c'est un code que j'ai écrit pour mon propre apprentissage. .. Dans cet exemple de source, la méthode d'envoi de la transaction est créée avec et sans signature, respectivement, et les deux sont appelées dans l'ordre à partir de la méthode principale.

SendTransaction.java


package jp.ethereum.transaction;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;

import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.admin.methods.response.PersonalUnlockAccount;
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Transfer;
import org.web3j.utils.Convert.Unit;
import org.web3j.utils.Numeric;

public class SendTransaction {

  // ①
  public static final Admin web3j = Admin.build(new HttpService("http://127.0.0.1:8545"));

  public static void main(String args[]) {
    try {
      // ②
      //Obtenir les informations d'identification de l'expéditeur de la transaction
      //Les informations d'identification incluent les clés publiques et privées
      String password = "password";
      Credentials credentials = WalletUtils.loadCredentials(password, "Chemin complet du fichier de clé privée");

      String toAddress = "0x66b4e7be902300f9a15d900822bbd8803be87391";

      SendTransaction tx= new SendTransaction();

      //Envoi d'une transaction
      tx.sendTransaction(credentials, password, toAddress, 10);

      //Envoyer une transaction signée
      TransactionReceipt receipt = tx.sendSignedTransaction(credentials, password, toAddress);

      if (receipt != null) System.out.println(receipt.getTransactionHash()) ;

    }catch(IOException | CipherException ex) {
      ex.printStackTrace();
    }
  }

  public TransactionReceipt sendTransaction(Credentials credentials, String password, String toAddress, long value) {

    TransactionReceipt receipt = null;
      try {
        //Générer une transaction
        // "personal_unlockAccount"Envoyez une demande et recevez une réponse
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //adresse
            password  //mot de passe
            ).send();

        //Si le déverrouillage est réussi, envoyez Ether
        if (unlockAccountResponse.getResult()) {
          //Envoyez une transaction. Aucune réponse n'est renvoyée tant qu'elle n'est pas chargée dans le bloc
          receipt = Transfer.sendFunds(web3j, credentials, toAddress, BigDecimal.valueOf(value), Unit.ETHER).send();
        }
      }catch(IOException | TransactionException ex) {
        ex.printStackTrace();
      }catch(Exception ex) {
        ex.printStackTrace();
      }
    return receipt;
  }
  public TransactionReceipt sendSignedTransaction(Credentials credentials, String password, String toAddress) {

      TransactionReceipt receipt = null;
      try {
        //Générer une transaction
        // "personal_unlockAccount"Envoyez une demande et recevez une réponse
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //adresse
            password  //mot de passe
            ).send();

        //Si le déverrouillage est réussi, envoyez Ether
        if (unlockAccountResponse.getResult()) {
            // "eth_sendTransaction"Créez un objet à passer à l'argument de
          RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
            BigInteger.valueOf(10),     // nonce
            BigInteger.valueOf(700),     // gasPrice
            BigInteger.valueOf(4712388),   // gasLimit
            toAddress,             // to
            BigInteger.valueOf(101)     // value
            );

          //Signez la transaction
          byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
          String hexValue = Numeric.toHexString(signedMessage);

          //Envoi d'une transaction
          EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
          String response = ethSendTransaction.getRawResponse();
          String transactionHash = ethSendTransaction.getTransactionHash();

          Optional<TransactionReceipt> transactionReceipt = null;
          int retry = 0;

          //Suivi des transactions
          if(transactionHash != null) {
            do {
            System.out.printf("%3d checking if transaction " + transactionHash + " is mined....\n" ,retry);
              EthGetTransactionReceipt ethGetTransactionReceiptResp = 
                  web3j.ethGetTransactionReceipt(transactionHash).send();
                transactionReceipt = ethGetTransactionReceiptResp.getTransactionReceipt();

                Thread.sleep(3000);
                retry++;
            }while(!transactionReceipt.isPresent() && retry < 100);
          } else {
            System.out.println("Transaction Send failed...");
            System.out.println("Message:" + ethSendTransaction.getError().getMessage());
            System.out.println("Data   :" + ethSendTransaction.getError().getData());
          }
        }
      }catch(IOException | InterruptedException ex) {
        ex.printStackTrace();
      }catch(Exception ex) {
        ex.printStackTrace();
      }
    return receipt;
  }
}

Je compléterai les points qui sont susceptibles d'être des points.

Connectez-vous à Ethereum

Connectez-vous à Ethereum

SendTransaction.java


// ①
public static final Admin admin = Admin.build(new HttpService("http://127.0.0.1:8545"));

Ici, nous créons une instance de la classe Admin. La classe Admin est une classe qui hérite de la classe Web3j et vous pouvez utiliser des méthodes qui utilisent des informations personnelles qui ne sont pas implémentées dans la classe Web3j. Utilisez la classe Admin au lieu de Web3j car l'envoi de transactions nécessite le déverrouillage du compte.

L'URL spécifiée dans l'argument sera l'adresse spécifiée dans l'option "--rpcaddr" au démarrage de geth. Si vous ne spécifiez pas le port, ce sera "8545".

Obtenez la clé privée

SendTransaction.java


//Obtenir les informations d'identification de l'expéditeur de la transaction
//Les informations d'identification incluent les clés publiques et privées
String password = "password";
Credentials credentials = WalletUtils.loadCredentials(password, "Chemin complet du fichier de clé privée");

Obtenez les informations de clé privée avec la méthode WalletUtils.loadCredentials. Mot de passe du compte utilisateur comme premier argument Spécifiez le chemin (y compris le nom de fichier) du fichier de clé privée (fichier commençant par UTC) dans le deuxième argument.

Envoi d'une transaction

Tout ce que vous avez à faire est de déverrouiller votre compte et de soumettre votre transaction.

SendTransaction.java


  public TransactionReceipt sendTransaction(Credentials credentials, String password, String toAddress, long value) {

    TransactionReceipt receipt = null;
      try {
        //Générer une transaction
        // "personal_unlockAccount"Envoyez une demande et recevez une réponse
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //adresse
            password  //mot de passe
            ).send();

        //Si le déverrouillage est réussi, envoyez Ether
        if (unlockAccountResponse.getResult()) {
          //Envoyez une transaction. Aucune réponse n'est renvoyée tant qu'elle n'est pas chargée dans le bloc
          receipt = Transfer.sendFunds(web3j, credentials, toAddress, BigDecimal.valueOf(value), Unit.ETHER).send();
        }
      }catch(IOException | TransactionException ex) {
        ex.printStackTrace();
      }catch(Exception ex) {
        ex.printStackTrace();
      }
    return receipt;
  }

Le fait est que ce processus n'a pas renvoyé de réponse tant que la transaction n'a pas été prise dans le bloc. Bien que l'intervalle de génération de bloc soit plus court que Bitcoin, il semble qu'il sera nécessaire de le considérer s'il y a une situation pour l'utiliser dans une application réelle.

receipt = Transfer.sendFunds(web3j, credentials, toAddress, BigDecimal.valueOf(value), Unit.ETHER).send();

Résultat de l'exécution de la transmission de la transaction

Tout d'abord, vérifiez avec "eth.getTransaction" lorsque la transaction est générée.

INFO [09-15|23:28:07.213] Submitted transaction                    fullhash=0xfa7ab0924c82b9e45a10acd5c6b72136a088b4dee0d4d4810a2d4f4408c3ee97 recipient=0x66B4e7bE902300F9a15D900822Bbd8803Be87391

> eth.getTransaction("0xfa7ab0924c82b9e45a10acd5c6b72136a088b4dee0d4d4810a2d4f4408c3ee97")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a",
  gas: 21000,
  gasPrice: 1000000000,
  hash: "0xfa7ab0924c82b9e45a10acd5c6b72136a088b4dee0d4d4810a2d4f4408c3ee97",
  input: "0x",
  nonce: 7,
  r: "0x3ca5a820995553d30656f2218dc10729d3e0f660c35817bbd69845ac96dc6279",
  s: "0x2e915ae47699771108f65881273f464d70db0229ad12a94ac38746f498ea7ed3",
  to: "0x66b4e7be902300f9a15d900822bbd8803be87391",
  transactionIndex: 0,
  v: "0x1c",
  value: 10000000000000000000
}

La transaction a été créée. Exploitez et voyez s'il entre dans le bloc.

> eth.getTransaction("0xfa7ab0924c82b9e45a10acd5c6b72136a088b4dee0d4d4810a2d4f4408c3ee97")
{
  blockHash: "0xc9634aec9670d312759a0e12ea5fee54948688c88e4d45a5b9cdbeef3c44c681",
  blockNumber: 2792,
  from: "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a",
  gas: 21000,
  gasPrice: 1000000000,
  hash: "0xfa7ab0924c82b9e45a10acd5c6b72136a088b4dee0d4d4810a2d4f4408c3ee97",
  input: "0x",
  nonce: 7,
  r: "0x3ca5a820995553d30656f2218dc10729d3e0f660c35817bbd69845ac96dc6279",
  s: "0x2e915ae47699771108f65881273f464d70db0229ad12a94ac38746f498ea7ed3",
  to: "0x66b4e7be902300f9a15d900822bbd8803be87391",
  transactionIndex: 0,
  v: "0x1c",
  value: 10000000000000000000
}

Il a été ramené en toute sécurité.

Envoyer une transaction signée

SendTransaction.java


  public TransactionReceipt sendSignedTransaction(Credentials credentials, String password, String toAddress) {

      TransactionReceipt receipt = null;
      try {
        //Générer une transaction
        // "personal_unlockAccount"Envoyez une demande et recevez une réponse
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //adresse
            password  //mot de passe
            ).send();

        //Si le déverrouillage est réussi, envoyez Ether
        if (unlockAccountResponse.getResult()) {
            // "eth_sendTransaction"Créez un objet à passer à l'argument de
          RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
            BigInteger.valueOf(10),     // nonce
            BigInteger.valueOf(700),     // gasPrice
            BigInteger.valueOf(4712388),   // gasLimit
            toAddress,             // to
            BigInteger.valueOf(101)     // value
            );

          //Signez la transaction
          byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
          String hexValue = Numeric.toHexString(signedMessage);

          //Envoi d'une transaction
          EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
          String response = ethSendTransaction.getRawResponse();
          String transactionHash = ethSendTransaction.getTransactionHash();

          Optional<TransactionReceipt> transactionReceipt = null;
          int retry = 0;

          //Suivi des transactions
          if(transactionHash != null) {
            do {
            System.out.printf("%3d checking if transaction " + transactionHash + " is mined....\n" ,retry);
              EthGetTransactionReceipt ethGetTransactionReceiptResp = 
                  web3j.ethGetTransactionReceipt(transactionHash).send();
                transactionReceipt = ethGetTransactionReceiptResp.getTransactionReceipt();

                Thread.sleep(3000);
                retry++;
            }while(!transactionReceipt.isPresent() && retry < 100);
          } else {
            System.out.println("Transaction Send failed...");
            System.out.println("Message:" + ethSendTransaction.getError().getMessage());
            System.out.println("Data   :" + ethSendTransaction.getError().getData());
          }
        }
      }catch(IOException | InterruptedException ex) {
        ex.printStackTrace();
      }catch(Exception ex) {
        ex.printStackTrace();
      }
    return receipt;
  }
}

Que fais tu

  1. Déverrouillez votre compte
  2. Création de l'objet de transaction
  3. Signez la transaction
  4. Envoyer la transaction
  5. Surveillance des transactions

Ce sera le flux. La surveillance des transactions vérifie si la valeur de hachage de la transaction spécifiée a été remplie dans le bloc.

Résultat d'exécution

La transaction a été créée.

INFO [09-15|23:29:23.752] Submitted transaction                    fullhash=0x533ff5d2635284d01d8e85015da00d8962de8b98bf5efaa6d9ceca3200243a88 recipient=0x66B4e7bE902300F9a15D900822Bbd8803Be87391

> eth.getTransaction("0x533ff5d2635284d01d8e85015da00d8962de8b98bf5efaa6d9ceca3200243a88")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a",
  gas: 4712388,
  gasPrice: 800,
  hash: "0x533ff5d2635284d01d8e85015da00d8962de8b98bf5efaa6d9ceca3200243a88",
  input: "0x",
  nonce: 10,
  r: "0xc8022528f46078b3e9a8f2a3174d147b85c23af6794fc8b07d58651931b7556f",
  s: "0x1ab35d15cf3afa6990bc6e96a593e6c2cba6432f769d0de919c770cec4a3f2c7",
  to: "0x66b4e7be902300f9a15d900822bbd8803be87391",
  transactionIndex: 0,
  v: "0x1b",
  value: 101
}

Cependant, cette transaction n'est pas incluse dans le bloc, peu importe la quantité de minage que je fais, car ma compréhension ne me rattrape pas. Y a-t-il un problème avec la valeur spécifiée pour la transaction? Ou n'est-il pas inclus dans le bloc sans valider la transaction signée?

Je continuerai d'étudier ce domaine.

finalement

J'étais juste en train d'apprendre en saisissant vaguement le contenu écrit dans le livre, mais quand j'ai cherché comment l'utiliser en Java, qui est mon langage le plus fort, les points qui avaient été soulignés jusqu'à présent sont devenus de plus en plus connectés.

Puisqu'il y a encore peu d'informations disponibles, j'aimerais être en mesure de sortir ce que j'ai appris de manière positive.

2019/09/17 Ajouté

Il indique que la transaction signée ne sera pas incluse dans le bloc, mais j'ai trouvé la solution (j'ai demandé à mon aîné et l'ai trouvée en 1 minute), alors je l'ai écrite dans l'article suivant.

Vérifiez si les transactions Ethereum ne sont pas incluses dans le bloc

Recommended Posts

Envoyer des transactions signées à l'aide de Web3j
[Hidden_field] Envoyez des informations en utilisant les rails hidden_field !!!!
[Ethereum] Obtenir des informations de bloc à l'aide de web3j