Comment envoyer une transaction signée à l'aide de la bibliothèque Java d'Ethereum "Web3j"
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
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".
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.
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();
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é.
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
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.
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.
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.
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