[Ethereum] web3jを使ってブロックの情報を取得する

# 記事の内容
Web3jを使ってブロックチェーンエクスプローラーの様なものを作っていたのですが、ブロックの取得方法を少し悩んでしまったのでメモを残します。

# 環境
- jdk:1.8
- web3j:4.5.0
- OS:Windows10

# ブロック情報の取得
早速ですが、サンプルで作ったコードがこちらです。

``` SampleBlock.java
import java.io.IOException;
import java.math.BigInteger;

import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.protocol.http.HttpService;

public class SampleBlock {

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

	public static void main(String[] args) {
		System.out.println("-------------------------Latest Block----------------------------------");
		EthBlock block = getLatestBlock();
		showBlockInfo(block);

		System.out.println("-------------------------Block Number(100)-----------------------------");
		block = getBlock(BigInteger.valueOf(100));
		showBlockInfo(block);
	}

	public static EthBlock getLatestBlock() {

		EthBlock latestBlock = null;
		try {
			latestBlock = web3j.ethGetBlockByNumber(
					DefaultBlockParameterName.LATEST,
					false).send();

		}catch(IOException e) {
			e.printStackTrace();
		}
		return latestBlock;
	}

	public static EthBlock getBlock(BigInteger blockNumber) {

		EthBlock block = null;
		try {
			block =web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(blockNumber), true).send();
		}catch(IOException e) {
			e.printStackTrace();
		}
		return block;
	}

	public static void showBlockInfo(EthBlock block) {
		System.out.println("Block Number: " + block.getBlock().getNumber());
		System.out.println("Block Size  : " + block.getBlock().getHash());
		System.out.println("Extra Data  : " + block.getBlock().getExtraData());
		System.out.println("Nonce       : " + block.getBlock().getNonce());
		System.out.println("Block Size  : " + block.getBlock().getSize());
	}
}
```
コードの内容は
1. 最新のブロックを取得して内容を表示
2. 指定したブロックナンバーのブロックを取得して内容を表示
この２つになります。

## 1.最新のブロック情報を取得して内容を表示
まずは最新の情報を取得します。

``` SampleBlock.java
public static EthBlock getLatestBlock() {

	EthBlock latestBlock = null;
	try {
		latestBlock = web3j.ethGetBlockByNumber(
				DefaultBlockParameterName.LATEST,
				false).send();
	}catch(IOException e) {
		e.printStackTrace();
	}
	return latestBlock;
}
public static void showBlockInfo(EthBlock block) {
	System.out.println("Block Number: " + block.getBlock().getNumber());
	System.out.println("Block Size  : " + block.getBlock().getHash());
	System.out.println("Extra Data  : " + block.getBlock().getExtraData());
	System.out.println("Nonce       : " + block.getBlock().getNonce());
	System.out.println("Block Size  : " + block.getBlock().getSize());
}
```

ethGetBlockByNumberの引数ですが、
第一引数：取得するブロックの情報
第二引数：トランザクションの詳細情報を取得するか否か
となります。

EthBlockクラスはBlockというインナークラスを保持しています。
ブロックの基本的な情報はBlockクラスのgetterメソッドを使用することで取得可能です。

## 2.指定したブロックナンバーのブロックを取得して内容を表示
ブロックナンバー100番を指定してブロックを取得します。

``` SampleBlock.java
public static EthBlock getBlock(BigInteger blockNumber) {

	EthBlock block = null;
	try {
		block =web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(blockNumber), true).send();
	}catch(IOException e) {
		e.printStackTrace();
	}
	return block;
}
```

最新のブロック情報を取得する時と使用するメソッドは一緒になります。
第一引数が「DefaultBlockParameterName.LATEST」ではなく、DefaultBlockParameter.valueOf(blockNumber)となります。

DefaultBlockParameter.valueOf(blockNumber)の引数に取得したいブロックナンバーをBigInteger型で設定するだけになります。

## 3.実行結果
最初のコードのmainメソッドの実行結果です

``` 実行結果
-------------------------Latest Block----------------------------------
Block Number: 1126
Block Size  : 0x43b54d8fa0721f48775662bc931f71b84037cf7697e008af630143e4be0d6c68
Extra Data  : 0xda83010900846765746888676f312e31322e378777696e646f7773
Nonce       : 8592711553053470949
Block Size  : 540
-------------------------Block Number(100)-----------------------------
Block Number: 100
Block Size  : 0x0e62799b40cc37228b74de6be9d6424277c7cc2ac50ad9370655851eea2e3feb
Extra Data  : 0xda83010900846765746888676f312e31322e378777696e646f7773
Nonce       : 5891392007347385592
Block Size  : 538
```
取得できる情報は他にもたくさんありますので、試してみていただけたらなと思います。

## 4.ブロックに取り込まれたトランザクションの情報を取得する
EthBlock.Blockクラス内にブロックに取り込まれたトランザクションの情報を保持しており、getTransactionsメソッドを使用して取得することができます。

参考にですが、トランザクションの情報を取得する処理です。

``` SampleBlock.java
public static List<TransactionObject> getTransactionList(BigInteger blockNumber) {

	List<TransactionObject> transactionList = new ArrayList<>();
	try {
		List<EthBlock.TransactionResult> txs = web3j.ethGetBlockByNumber(
				new DefaultBlockParameterNumber(blockNumber), true).send().getBlock().getTransactions();
			
		for(TransactionResult result: txs) {
			transactionList.add((TransactionObject)result.get());
		}
	}catch(IOException e) {
		e.printStackTrace();
	}
	return transactionList;
}
```

もっと良い方法がありそうな気がしますが、EthBlock.TransactionResultクラスからは情報を取得することができません。
TransactionResult内にTransactionObjectクラスを保持しているため、このクラスを通してトランザクションの情報を取得することが可能です。

# 最後に
思ったよりも簡単にブロックとトランザクションの情報を取得することができ、
数時間でethereumのブロックチェーンエクスプローラーを作ることが出来ました。