go-ethereumを使ってローカル環境でブロックチェーンを作成する

# go-ethereumを使ってローカル環境でブロックチェーンを作成する

## Ubuntuにgethをインストール

リポジトリの追加を行ってからインストールを行う

```
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum
```

正常にインストールできているか確認
```
$ geth --help
```

## マイニングと送金

### アカウントの作成
マイニングや送金を行うため、アカウントを2つ作成する。

dataディレクトリにアカウントを作成する。
```
$ geth account new --datadir data
```

パスワードを入力する
```
INFO [07-15|21:40:29.862] Maximum peer count                       ETH=50 LES=0 total=50
INFO [07-15|21:40:29.863] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:

Your new key was generated

Public address of the key:   0xBDdd36Ad46e52f833e4b912B2aeDA7Ad8CF54cb8
Path of the secret key file: data/keystore/UTC--2023-07-15T12-40-37.186591314Z--bddd36ad46e52f833e4b912b2aeda7ad8cf54cb8

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
```

これで1つアカウントができたため、2つ目も同様の方法で作成する。

※Public addressについては後で使用するのでメモしておきましょう。

---
### genesis.jsonの作成

```
{
  "config": {
    "chainId": 12345,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "clique": {
      "period": 5,
      "epoch": 30000
    }
  },
  "difficulty": "1",
  "gasLimit": "8000000",
  "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000E508ba2eF0075d89979dE7F5973db88F4d56B5e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "alloc": {
    "E508ba2eF0075d89979dE7F5973db88F4d56B5e3": { "balance": "100000000000000000000" },
    "681E49c8fa5705f0D404655dB2Ac06536939702c": { "balance": "10000000000000000000" }
  }
}
```

allocの中身は最初にethをどのくらい与えるかを設定できる。
アカウントを2つ作成したため2行記載されている。
wei単位で記載するため、1ethの場合、「1000000000000000000」と記載する。

---
### 初期化・起動
genesis.jsonに記載した内容で初期化する
```
$ geth init --datadir data genesis.json
```
出力
```
INFO [07-15|21:46:55.355] Maximum peer count                       ETH=50 LES=0 total=50
INFO [07-15|21:46:55.357] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [07-15|21:46:55.359] Set global gas cap                       cap=50,000,000
INFO [07-15|21:46:55.359] Initializing the KZG library             backend=gokzg
INFO [07-15|21:46:55.431] Defaulting to pebble as the backing database
INFO [07-15|21:46:55.431] Allocated cache and file handles         database=/home/server/test/data/geth/chaindata cache=16.00MiB handles=16
INFO [07-15|21:46:55.445] Opened ancient database                  database=/home/server/test/data/geth/chaindata/ancient/chain readonly=false
INFO [07-15|21:46:55.445] Writing custom genesis block
INFO [07-15|21:46:55.445] Persisted trie from memory database      nodes=4 size=477.00B time="17.024μs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=0 livesize=0.00B
INFO [07-15|21:46:55.448] Successfully wrote genesis state         database=chaindata                             hash=2cd0a6..7538fc
INFO [07-15|21:46:55.448] Defaulting to pebble as the backing database
INFO [07-15|21:46:55.448] Allocated cache and file handles         database=/home/server/test/data/geth/lightchaindata cache=16.00MiB handles=16
INFO [07-15|21:46:55.482] Opened ancient database                  database=/home/server/test/data/geth/lightchaindata/ancient/chain readonly=false
INFO [07-15|21:46:55.482] Writing custom genesis block
INFO [07-15|21:46:55.482] Persisted trie from memory database      nodes=4 size=477.00B time="10.986μs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=0 livesize=0.00B
INFO [07-15|21:46:55.484] Successfully wrote genesis state         database=lightchaindata                        hash=2cd0a6..7538fc
```

起動
```
$ geth --datadir data --networkid 12345　--nodiscover 
```
networkidはgenesis.jsonで指定してる値と同じにする。
起動することが確認出来たら一度Ctrl+Cで終了する

---
### マイニングと送金
プライベートネットでマイニングを開始する。

```
$ geth --datadir data --networkid 12345 --nodiscover --mine --unlock 0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3 --miner.etherbase 0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3
```

各オプションの説明

--datadir value         :初期化をおこなったディレクトリ
--networkid value       :genesis.jsonと同じ数字。mainnetが1を使用しているため他の数値を選択。今回はドキュメントと同じ[12345]を選択。
--nodiscover            :ノードの検索をしないようにする。デフォルトではノードの検索が行われる。
--mine                  :マイニングを許可する。デフォルトでは許可されていない。
--unlock value          :ウォレットへのアクセスを許可する。実行後パスワードを入力する必要がある。
--miner.etherbase value :マイニングの報酬を受け取るアドレス

unlockとminer.etherbaseは作成したユーザのアドレスを指定しておく。
unlockを指定した場合、実行後、該当アカウントのパスワードを入力する必要がある。

パスワード入力
```
Unlocking account 0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3 | Attempt 1/3
Password:
```

認証が正常に通った場合
```
INFO [07-18|13:17:58.377] Unlocked account                         address=0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3
INFO [07-18|13:17:58.377] Transaction pool price threshold updated price=0
INFO [07-18|13:17:58.377] Transaction pool price threshold updated price=1,000,000,000
```

正常にマイニングされている場合
```
INFO [07-18|13:17:58.377] Commit new sealing work                  number=71 sealhash=b99eb3..acf368 uncles=0 txs=0 gas=0 fees=0 elapsed="112.599μs"
INFO [07-18|13:17:58.378] Commit new sealing work                  number=71 sealhash=b99eb3..acf368 uncles=0 txs=0 gas=0 fees=0 elapsed="525.944μs"
INFO [07-18|13:17:58.378] Successfully sealed new block            number=71 sealhash=b99eb3..acf368 hash=0e826d..6ebb9b elapsed="633.089μs"
```
---
### 対話型コンソールで送金
マイニング実行後に他のターミナルを開き、下記コマンドを実行することで、対話型のコンソールにアタッチする。
```
$ geth attach data/geth.ipc
```

アカウントの確認
```
> eth.accounts
["0xe508ba2ef0075d89979de7f5973db88f4d56b5e3", "0x681e49c8fa5705f0d404655db2ac06536939702c"]
```

マイニングが実行されていることの確認
```
> eth.mining
true
```

現在のブロック番号の確認
```
> eth.blockNumber
103
```

アカウント1からアカウント2に送金を行う
```
tx = {from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, 'ether')}
eth.sendTransaction(tx)
```

送金後、各アカウントの所有ethを確認する。
※何度か送金を行ったので、出力される数字が違うかも・・・
```
> eth.getBalance(eth.accounts[0])
91000000000000000000
> eth.getBalance(eth.accounts[1])
19000000000000000000
```

送金を行ったときの出力
```
INFO [07-18|13:41:40.207] Submitted transaction                    hash=0x0278dbcc3e08ff79856fb5aa838155e5847247d66b4b9363419d5939d61b5cb4 from=0xE508ba2eF0075d89979dE7F5973db88F4d56B5e3 nonce=3 recipient=0x681E49c8fa5705f0D404655dB2Ac06536939702c value=5,000,000,000,000,000,000
INFO [07-18|13:41:41.004] Commit new sealing work                  number=179 sealhash=0ac86f..5c8ea8 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed="977.801μs"
INFO [07-18|13:41:42.003] Successfully sealed new block            number=179 sealhash=0ac86f..5c8ea8 hash=04255b..d2f838 elapsed=998.786ms
```

## 終わりに
自分が実際にプライベートネットを構築する際、情報が古くエラーが出たりメソッドが廃止されていたりとなかなか実装に手間取ったので情報共有のために記事を作成しました。
もし、ご指摘やもっと簡単にできる方法などがあれば教えていただきたいです。
この記事で誰かの役に立てると嬉しいです。