[JAVA] Senden Sie signierte Transaktionen mit Web3j

Artikelinhalt

So senden Sie eine signierte Transaktion mit der Java-Bibliothek "Web3j" von Ethereum

Umgebung

Implementierung

Es ist ziemlich rau, weil es ein Code ist, den ich für mein eigenes Lernen geschrieben habe. .. In dieser Beispielquelle wird die Sendemethode der Transaktion mit bzw. ohne Signatur erstellt, und beide werden in der Reihenfolge von der Hauptmethode aufgerufen.

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 {
      // ②
      //Anmeldeinformationen des Transaktionssenders abrufen
      //Zu den Anmeldeinformationen gehören öffentliche und private Schlüssel
      String password = "password";
      Credentials credentials = WalletUtils.loadCredentials(password, "Vollständiger Pfad der privaten Schlüsseldatei");

      String toAddress = "0x66b4e7be902300f9a15d900822bbd8803be87391";

      SendTransaction tx= new SendTransaction();

      //Senden einer Transaktion
      tx.sendTransaction(credentials, password, toAddress, 10);

      //Signierte Transaktion senden
      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 {
        //Eine Transaktion generieren
        // "personal_unlockAccount"Senden Sie eine Anfrage und erhalten Sie eine Antwort
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //Adresse
            password  //Passwort
            ).send();

        //Wenn das Entsperren erfolgreich ist, senden Sie Ether
        if (unlockAccountResponse.getResult()) {
          //Senden Sie eine Transaktion. Es wird keine Antwort zurückgegeben, bis sie in den Block geladen wird
          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 {
        //Eine Transaktion generieren
        // "personal_unlockAccount"Senden Sie eine Anfrage und erhalten Sie eine Antwort
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //Adresse
            password  //Passwort
            ).send();

        //Wenn das Entsperren erfolgreich ist, senden Sie Ether
        if (unlockAccountResponse.getResult()) {
            // "eth_sendTransaction"Erstellen Sie ein Objekt, das an das Argument von übergeben werden soll
          RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
            BigInteger.valueOf(10),     // nonce
            BigInteger.valueOf(700),     // gasPrice
            BigInteger.valueOf(4712388),   // gasLimit
            toAddress,             // to
            BigInteger.valueOf(101)     // value
            );

          //Unterzeichnen Sie die Transaktion
          byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
          String hexValue = Numeric.toHexString(signedMessage);

          //Senden einer Transaktion
          EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
          String response = ethSendTransaction.getRawResponse();
          String transactionHash = ethSendTransaction.getTransactionHash();

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

          //Transaktionsüberwachung
          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;
  }
}

Ich werde die Punkte ergänzen, die wahrscheinlich Punkte sind.

Stellen Sie eine Verbindung zu Ethereum her

Stellen Sie eine Verbindung zu Ethereum her

SendTransaction.java


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

Hier erstellen wir eine Instanz der Admin-Klasse. Die Admin-Klasse ist eine Klasse, die von der Web3j-Klasse erbt. Sie können Methoden verwenden, die persönliche Informationen verwenden, die nicht in der Web3j-Klasse implementiert sind. Verwenden Sie die Admin-Klasse anstelle von Web3j, da zum Senden von Transaktionen das Konto entsperrt werden muss.

Die im Argument angegebene URL ist die Adresse, die in der Option "--rpcaddr" angegeben ist, wenn geth gestartet wird. Wenn Sie den Port nicht angeben, lautet er "8545".

Holen Sie sich den privaten Schlüssel

SendTransaction.java


//Anmeldeinformationen des Transaktionssenders abrufen
//Zu den Anmeldeinformationen gehören öffentliche und private Schlüssel
String password = "password";
Credentials credentials = WalletUtils.loadCredentials(password, "Vollständiger Pfad der privaten Schlüsseldatei");

Rufen Sie die privaten Schlüsselinformationen mit der WalletUtils.loadCredentials-Methode ab. Benutzerkontokennwort als erstes Argument Geben Sie im zweiten Argument den Pfad (einschließlich des Dateinamens) der privaten Schlüsseldatei (Datei beginnend mit UTC) an.

Senden einer Transaktion

Sie müssen lediglich Ihr Konto entsperren und Ihre Transaktion übermitteln.

SendTransaction.java


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

    TransactionReceipt receipt = null;
      try {
        //Eine Transaktion generieren
        // "personal_unlockAccount"Senden Sie eine Anfrage und erhalten Sie eine Antwort
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //Adresse
            password  //Passwort
            ).send();

        //Wenn das Entsperren erfolgreich ist, senden Sie Ether
        if (unlockAccountResponse.getResult()) {
          //Senden Sie eine Transaktion. Es wird keine Antwort zurückgegeben, bis sie in den Block geladen wird
          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;
  }

Der Punkt ist, dass dieser Prozess keine Antwort zurückgab, bis die Transaktion in den Block aufgenommen wurde. Obwohl das Blockgenerierungsintervall kürzer als bei Bitcoin ist, scheint es notwendig zu sein, es zu berücksichtigen, wenn es eine Situation gibt, in der es in einer tatsächlichen Anwendung verwendet werden kann.

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

Ausführungsergebnis der Transaktionsübertragung

Überprüfen Sie zunächst mit "eth.getTransaction", wann die Transaktion generiert wird.

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
}

Die Transaktion wurde erstellt. Bergbau und sehen, ob es in den Block gelangt.

> 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
}

Es wurde sicher aufgenommen.

Signierte Transaktion senden

SendTransaction.java


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

      TransactionReceipt receipt = null;
      try {
        //Eine Transaktion generieren
        // "personal_unlockAccount"Senden Sie eine Anfrage und erhalten Sie eine Antwort
        PersonalUnlockAccount unlockAccountResponse = web3j.personalUnlockAccount(
            credentials.getAddress(), //Adresse
            password  //Passwort
            ).send();

        //Wenn das Entsperren erfolgreich ist, senden Sie Ether
        if (unlockAccountResponse.getResult()) {
            // "eth_sendTransaction"Erstellen Sie ein Objekt, das an das Argument von übergeben werden soll
          RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
            BigInteger.valueOf(10),     // nonce
            BigInteger.valueOf(700),     // gasPrice
            BigInteger.valueOf(4712388),   // gasLimit
            toAddress,             // to
            BigInteger.valueOf(101)     // value
            );

          //Unterzeichnen Sie die Transaktion
          byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
          String hexValue = Numeric.toHexString(signedMessage);

          //Senden einer Transaktion
          EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
          String response = ethSendTransaction.getRawResponse();
          String transactionHash = ethSendTransaction.getTransactionHash();

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

          //Transaktionsüberwachung
          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;
  }
}

Was machst du

  1. Entsperren Sie Ihr Konto
  2. Erstellung eines Transaktionsobjekts
  3. Unterzeichnen Sie die Transaktion
  4. Transaktion senden
  5. Transaktionsüberwachung

Es wird der Fluss sein. Die Transaktionsüberwachung prüft, ob der Hashwert der angegebenen Transaktion in den Block eingefügt wurde.

Ausführungsergebnis

Die Transaktion wurde erstellt.

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
}

Diese Transaktion ist jedoch nicht im Block enthalten, egal wie viel Mining ich mache, da mein Verständnis nicht aufholt. Stimmt etwas mit dem für die Transaktion angegebenen Wert nicht? Oder ist es nicht im Block enthalten, ohne die signierte Transaktion zu validieren?

Ich werde diesen Bereich weiter studieren.

Schließlich

Ich habe nur gelernt, indem ich den Inhalt des Buches vage eingegeben habe, aber als ich untersuchte, wie man ihn in Java, meiner stärksten Sprache, verwendet, wurden die Punkte, auf die bisher hingewiesen wurde, immer mehr miteinander verbunden.

Da noch wenig Informationen verfügbar sind, möchte ich das Gelernte positiv ausgeben können.

2019/09/17 Hinzugefügt

Es heißt, dass signierte Transaktionen nicht im Block enthalten sind, aber ich habe die Lösung gefunden (ich habe meine Senioren gefragt und sie in 1 Minute gefunden), also habe ich sie im folgenden Artikel geschrieben.

Überprüfen Sie, ob Ethereum-Transaktionen nicht im Block enthalten sind

Recommended Posts

Senden Sie signierte Transaktionen mit Web3j
[Hidden_field] Sende Informationen mit Rails hidden_field !!!!
[Ethereum] Blockinformationen mit web3j abrufen