イーサリアム開発環境(Geth)を構築して送金処理を行うまで

ブロックチェーンを自分でも動かしてみたかったので、イーサリアムの環境を構築して、送金処理まで実施してみました。  
コマンドラインベースで実行してみたかったので、今回はGethを利用します。  

# 環境
MacBook Air M1 2020
メモリ16GB
macOS 13.0

# Gethインストール

事前にHomebrewをセットアップしてください。  
Gethをインストールする為に以下コマンドを実行してください。  
```
$ brew tap ethereum/ethereum
$ brew install ethereum
```

# 準備

任意の場所に作業用フォルダを作成します。私は以下の通り作成しました。  
```
$ mkdir ~/projects/ethereum/
$ mkdir ~/projects/ethereum/node1
$ cd ~/projects/ethereum/
```

ブロックチェーンのGenesisブロック(最初のブロック)を作成します。
genesis.jsonを以下の通り作成します。
```
{
  "config": {
    "chainId": 100,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0
  },
  "alloc": {},
  "coinbase": "0x0000000000000000000000000000000000000000",
  "difficulty": "0x20000",
  "extraData": "",
  "gasLimit": "0x2fefd8",
  "nonce": "0x0000000000000042",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp": "0x00"
}
```
chainIdには任意のIDを指定することができますが、以下は予約されているため避けた方が良いと思います。今回は100を指定しました。  
1, 2, 3, 4, 5, 42, 1337
allocにユーザ(アドレス)を指定すると、最初にETHを割り当てできるようです。今回はGenesisブロックを作成した後にユーザを作成するので指定していません。  


# Geth初期化
イーサリアムノードを作成します。
以下コマンドを実行します。  
```
$ geth --datadir ~/projects/ethereum/node1 init ~/projects/ethereum/genesis.json
INFO [12-04|18:18:51.854] Maximum peer count                       ETH=50 LES=0 total=50
（省略）
INFO [11-09|19:24:48.796] Successfully wrote genesis state         database=lightchaindata hash=d118bd..7a409f
```
node1フォルダが生成され、その下にはgethとkeystoreフォルダが生成されます。

# Geth起動

Gethを起動します。
以下コマンドを実行します。
```
$ geth --networkid 100 --nodiscover --maxpeers 0 --datadir ~/projects/ethereum/node1 console 2>> ~/projects/ethereum/node1/geth.log
Welcome to the Geth JavaScript console!
（省略）
To exit, press ctrl-d or type exit
>
```
Genesisブロックが生成されているか確認します。
以下コマンドを実行します。
```
> eth.getBlock(0)
{
  baseFeePerGas: 1000000000,
  difficulty: 131072,
  extraData: "0x",
  gasLimit: 3141592,
  gasUsed: 0,
  hash: "0xd118bd9c6cdf4be6844c7af2b5d86e0d23e91cbe46955c0c23a61dfa577a409f",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 512,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 131072,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
```

# アカウントの作成
Etherの採掘や送金処理を行うにはアカウントの作成が必要になります。
今回は２つアカウントを作成します。
以下コマンドを実行します。引数はパスワードになります。
```
> personal.newAccount("pass0")
"0xf53ac86545559b81188c48ecfd89183e74a05ba5"
> personal.newAccount("pass1")
"0x3732e0d588244ea6d233e41b0e3facfda0010627"
```

作成したアカウントを確認します。
```
> eth.accounts
["0xf53ac86545559b81188c48ecfd89183e74a05ba5", "0x3732e0d588244ea6d233e41b0e3facfda0010627"]
```

アカウントの残高を確認します。どちらも0のはずです。
```
> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0
```

# マイニングを行う

マイニング成功時に報酬を受け取るアカウントを確認します。
このアカウントはEtherbaseと呼ばれます。
最初に作ったアカウントが表示されるはずです。
```
> eth.coinbase
"0xf53ac86545559b81188c48ecfd89183e74a05ba5"
```

マイニングを開始します。
```
> miner.start(1)
null
```

少し待ってからブロック数が増えていることを確認します。
```
> eth.mining
true
> eth.blockNumber
3
```

ブロック数が増えていたら一旦マイニングを止めます。
```
> miner.stop()
null
```

先ほどGenesisブロック(最初のブロック)が作成されていることを確認しました。今度は２番目のブロックを確認してみます。
```
> eth.getBlock(1)
{
  baseFeePerGas: 875000000,
  difficulty: 131072,
  extraData: "0xd983010a1a846765746888676f312e31392e338664617277696e",
  gasLimit: 3144658,
  gasUsed: 0,
  hash: "0x5e52e90aedaf2aae18a13952aa574f3005b3e523e4c1740f3d1ce2a45f2b59e8",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xf53ac86545559b81188c48ecfd89183e74a05ba5",
  mixHash: "0x26642ebcc7510e2539394d6f14e7c98609251b7e2da01c4109f1453df389eb27",
  nonce: "0x2b5b574a136d247e",
  number: 1,
  parentHash: "0xd118bd9c6cdf4be6844c7af2b5d86e0d23e91cbe46955c0c23a61dfa577a409f",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 542,
  stateRoot: "0xeab84264a580d4d66d1353c60d39ddbda0a6ef5be87c8f04ed761f4c35e8b964",
  timestamp: 1670146603,
  totalDifficulty: 262144,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
```
ブロックチェーンなので、parentHashの値とGenesisブロックのhashの値が同じはずです。

マイニングを行ったのでアカウントの残高を確認します。
Etherbaseがマイニングの報酬を受け取っているはずです。
```
> eth.getBalance(eth.accounts[0])
12000000000000000000
> eth.getBalance(eth.accounts[1])
0
```

# Etherの送金

受け取った報酬をもう一つのアカウントに送金してみます。
送信元アカウントをアンロックします。(300秒間だけEtherの送金が可能になります)
コマンド実行時にアカウントのパスワードを求められます。

```
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xf53ac86545559b81188c48ecfd89183e74a05ba5
Passphrase: 
true
```

accounts[0]からaccounts[1]に10ether送金します。
戻り値はトランザクションのhash値です。
```
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(10, "ether")})
"0xb7f3394596a2baab10f279442bdc8eaf4a2f43675665159aa5eb54e56ef9062a"
```

この時点ではトランザクションはまだ処理されていません。
未処理のトランザクションを確認します。
```
> eth.pendingTransactions
[{
    accessList: [],
    blockHash: null,
    blockNumber: null,
    chainId: "0x64",
    from: "0xf53ac86545559b81188c48ecfd89183e74a05ba5",
    gas: 21000,
    gasPrice: 1897590638,
    hash: "0xb7f3394596a2baab10f279442bdc8eaf4a2f43675665159aa5eb54e56ef9062a",
    input: "0x",
    maxFeePerGas: 1897590638,
    maxPriorityFeePerGas: 1000000000,
    nonce: 0,
    r: "0xb02fc9f6bd98a3d73e43513b2c55bf9ee2c1d951969c08f56c322f626fd97d65",
    s: "0x638d333999a15494c8d8acffba732641ec4dc1cf15db068feff79368f234a5da",
    to: "0x3732e0d588244ea6d233e41b0e3facfda0010627",
    transactionIndex: null,
    type: "0x2",
    v: "0x0",
    value: 10000000000000000000
}]
```
送金実行時の戻り値とhashが同じはずです。

このトランザクションをブロックチェーンに書き込みます。
マイニングを開始して、トランザクションを処理されたら(未処理のトランザクションが無くなる)、マイニングを止めます。
```
> miner.start(1)
null
> eth.pendingTransactions
[]
> miner.stop()
null
```

送金結果を確認する為に、アカウントの残高を確認します。
```
> eth.getBalance(eth.accounts[0])
23999991753385995000
> eth.getBalance(eth.accounts[1])
10000000000000000000
```

送金処理のトランザクションを確認します。
引数のトランザクションのhashを指定します。
```
> eth.getTransaction("0xb7f3394596a2baab10f279442bdc8eaf4a2f43675665159aa5eb54e56ef9062a")
{
  accessList: [],
  blockHash: "0x5fb6ce98cfa6aab051de0faf81b4d53ae4e32426a8c0928d4c1a1ce791124cb8",
  blockNumber: 7,
  chainId: "0x64",
  from: "0xf53ac86545559b81188c48ecfd89183e74a05ba5",
  gas: 21000,
  gasPrice: 1392695905,
  hash: "0xb7f3394596a2baab10f279442bdc8eaf4a2f43675665159aa5eb54e56ef9062a",
  input: "0x",
  maxFeePerGas: 1897590638,
  maxPriorityFeePerGas: 1000000000,
  nonce: 0,
  r: "0xb02fc9f6bd98a3d73e43513b2c55bf9ee2c1d951969c08f56c322f626fd97d65",
  s: "0x638d333999a15494c8d8acffba732641ec4dc1cf15db068feff79368f234a5da",
  to: "0x3732e0d588244ea6d233e41b0e3facfda0010627",
  transactionIndex: 0,
  type: "0x2",
  v: "0x0",
  value: 10000000000000000000
}
```
7番目のブロックにトランザクションが書き込まれました。
念の為、7番目のブロックも確認してみます。
```
> eth.getBlock(7)
{
  baseFeePerGas: 392695905,
  difficulty: 131072,
  extraData: "0xd983010a1a846765746888676f312e31392e338664617277696e",
  gasLimit: 3163117,
  gasUsed: 21000,
  hash: "0x5fb6ce98cfa6aab051de0faf81b4d53ae4e32426a8c0928d4c1a1ce791124cb8",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xf53ac86545559b81188c48ecfd89183e74a05ba5",
  mixHash: "0xfce094b0ed426ef4d2a444a6393abc72f6c3d59f65a7e1cea2822f3339081943",
  nonce: "0x2130afc1acf78b8b",
  number: 7,
  parentHash: "0xec7af5f1bcf59844f13f100341135bea3f09d448e86661cbd19c520c275bf9cc",
  receiptsRoot: "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 664,
  stateRoot: "0x9e23b2f61c6a9fe7473c13e4f34757d695155e67cd71b28a352de04b969252a9",
  timestamp: 1670147647,
  totalDifficulty: 1049536,
  transactions: ["0xb7f3394596a2baab10f279442bdc8eaf4a2f43675665159aa5eb54e56ef9062a"],
  transactionsRoot: "0x1210d01d8d3e48286c3e6a7f3d4ee8db81222411595e6dae53378109300034cd",
  uncles: []
}
```
送金トランザクションのblockHashとブロック(7)のhashが同じであることが確認できました。
また、ブロック(7)のtransactionsに送金トランザクションのhashが書き込まれています。

# 参考サイト

https://note.com/npaka/n/n707a8bee42ca