LoginSignup
2
4

More than 3 years have passed since last update.

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

Posted at

記事の内容

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に変わりました。

所感

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

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4