Help us understand the problem. What is going on with this article?

Ethereum トランザクションがブロックに取り込まれない場合の確認

記事の内容

web3jを使って署名付きトランザクションを発行する記事を書きましたが、そのやり方ではトランザクションがブロックに取り込まれませんでした。

Web3jを使って署名付きトランザクションを送信する

確認方法も含め、修正方法を残します。

トランザクションプールの確認

gethのJavaScriptコンソールで「txpool」を確認します。

> txpool
{
  content: {
    pending: {
      0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: {
        19: {...}
      }
    },
    queued: {
      0x66B4e7bE902300F9a15D900822Bbd8803Be87391: {
        1: {...},
        100: {...},
        5: {...}
      },
      0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: {
        100: {...}
      }
    }
  },
  inspect: {
    pending: {
      0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: {
        19: "0xf5ad7542173e8944D1aE16B4394eAA34cfdA4814: 0 wei + 200000 gas × 500 wei"
      }
    },
    queued: {
      0x66B4e7bE902300F9a15D900822Bbd8803Be87391: {
        1: "0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: 0 wei + 4712388 gas × 100 wei",
        100: "0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: 0 wei + 4712388 gas × 100 wei",
        5: "0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: 0 wei + 4712388 gas × 100 wei"
      },
      0x945Cd603A6754cB13C3D61d8fe240990f86f9f8A: {
        100: "0x66B4e7bE902300F9a15D900822Bbd8803Be87391: 1000000000000000 wei + 200000 gas × 100 wei"
      }
    }
  },
  status: {
    pending: 1,
    queued: 4
  },
  getContent: function(callback),
  getInspect: function(callback),
  getStatus: function(callback)
}

ここでポイントとなるのが、「queued」です。
トランザクションが作成されると、queuedに入り、署名のチェックなど色々なチェックが行われ、チェックが問題なければ「pending」に移り、ブロックに格納されるのを待つみたいです。

こちらのサイトで詳しく説明されていました。
EthereumのPending TransactionとTransaction Poolについて

Web3jを使った署名付きトランザクションの送信方法

Web3jを使って署名付きトランザクションを送信する
この記事に書いたsendSignedTransactionを修正しました。

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

      TransactionReceipt receipt = null;
      try {
        // nonce値を取得する
        EthGetTransactionCount ethTransactionCount =
            web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.PENDING).send();
        BigInteger nonce = ethTransactionCount.getTransactionCount();

        // "eth_sendTransaction"の引数に渡すオブジェクトを作成
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
            nonce,                        // nonce
            BigInteger.valueOf(100),     // gasPrice
            BigInteger.valueOf(4712388), // gasLimit
            toAddress,                    // to
            BigInteger.valueOf(1010000)  // value
            );

        // トランザクションに署名
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);

        EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
        String transactionHash = ethSendTransaction.getTransactionHash();

        // トランザクションの送信
        Optional<TransactionReceipt> transactionReceipt = null;
        int retry = 0;

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

間違っていた点としては、RawTransactionに設定しているnonce値が固定値になっていたため、トランザクションのチェック処理に引っ掛かりqueuedに溜まったままとなっていました。

RawTransactionを送信した直後にトランザクションの情報を確認してみました。

INFO [09-17|20:52:21.455] Submitted transaction                    fullhash=0x84b89a096fcb1a5381319cf08348f633ebe2dc2ef93ba48b0c05d5b460110970 recipient=0x66B4e7bE902300F9a15D900822Bbd8803Be87391
> eth.getTransaction("0x84b89a096fcb1a5381319cf08348f633ebe2dc2ef93ba48b0c05d5b460110970")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a",
  gas: 4712388,
  gasPrice: 100,
  hash: "0x84b89a096fcb1a5381319cf08348f633ebe2dc2ef93ba48b0c05d5b460110970",
  input: "0x",
  nonce: 24,
  r: "0xd6bb90deea18af081795bc335c3323389c830721d5d7db54f6ef6c19f3425358",
  s: "0x4e99740c21f5ef2f3debafcff0256340dfff07e00a86801eb90d72804439d602",
  to: "0x66b4e7be902300f9a15d900822bbd8803be87391",
  transactionIndex: 0,
  v: "0x1c",
  value: 1010000
}
> txpool.status
{
  pending: 1,
  queued: 0
}

pendingにトランザクションが溜まりました。
マイニングした後にも確認しました。

> eth.getTransaction("0x84b89a096fcb1a5381319cf08348f633ebe2dc2ef93ba48b0c05d5b460110970")
{
  blockHash: "0x3a150aebfffbe81804f4d5b193e3a22aea79654c3bd5c53d2a3df8d7d8417c34",
  blockNumber: 3066,
  from: "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a",
  gas: 4712388,
  gasPrice: 100,
  hash: "0x84b89a096fcb1a5381319cf08348f633ebe2dc2ef93ba48b0c05d5b460110970",
  input: "0x",
  nonce: 24,
  r: "0xd6bb90deea18af081795bc335c3323389c830721d5d7db54f6ef6c19f3425358",
  s: "0x4e99740c21f5ef2f3debafcff0256340dfff07e00a86801eb90d72804439d602",
  to: "0x66b4e7be902300f9a15d900822bbd8803be87391",
  transactionIndex: 0,
  v: "0x1c",
  value: 1010000
}

> txpool.status
{
  pending: 0,
  queued: 0
}

ブロックに格納され、pendingが0に変わりました。

所感

トランザクションに設定する内容やトランザクションが作られてからブロックに取り込まれるまでの流れを正確に理解する必要があると実感しました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away