初歩の初歩から再現（断念）〜NFT, Web3完全に理解した　になるためのチュートリアル〜

NFT, Web3を技術的に理解したいと思い、下記の記事を辿りました。

https://note.com/djrio/n/n9385c61aa402

この記事を私に紹介したホモサピエンスが最後まで再現していなかったので、案外たどるのが大変なのでは？と思い、同じ道を辿る人のために、再現記事を書きました。

1-1から4までありますが、私のようなしょぼしょぼ初心者だと1の環境構築でつまづきがちなので前半こそ丁寧に振り返ります。ちなみに理論は実装してから理解すれば良いと私は個人的に考えているので、0はスルーが良いと思います。

# 1-1 gethのインストール
まず、note記事通りに以下をターミナルで実行しました。

```
$ brew tap ethereum/ethereum
$ brew install ethereum
```


実行結果は次の画像になりました。すでにインストールを試したことがあるのでwanrningが出てますね。

![スクリーンショット 2022-09-02 21.56.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/97db448b-174d-8c71-68f2-51e7a612ce1d.png)

reinstallの後にターミナルが特に動かぬまま終了したので、怪しいと思い、念の為noteで参考とされていた公式記事から順に下のコードを実行しました。

```
brew -v
```

```
brew install ethereum --devel
```

```
brew update 
brew upgrade 
brew reinstall ethereum
```

実行結果は下の感じです。

```
(base) morozumikohei@MacBook-Air ~ % brew install ethereum --devel
Usage: brew install [options] formula|cask [...]

Install a formula or cask. Additional options specific to a formula may be
appended to the command.

Unless HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK is set, brew upgrade or brew
reinstall will be run for outdated dependents and dependents with broken
linkage, respectively.

Unless HOMEBREW_NO_INSTALL_CLEANUP is set, brew cleanup will then be run for
the installed formulae or, every 30 days, for all formulae.

Unless HOMEBREW_NO_INSTALL_UPGRADE is set, brew install formula will
upgrade formula if it is already installed but outdated.

  -d, --debug                      If brewing fails, open an interactive
                                   debugging session with access to IRB or a
                                   shell inside the temporary build directory.
  -f, --force                      Install formulae without checking for
                                   previously installed keg-only or non-migrated
                                   versions. When installing casks, overwrite
                                   existing files (binaries and symlinks are
                                   excluded, unless originally from the same
                                   cask).
  -v, --verbose                    Print the verification and postinstall steps.
      --formula, --formulae        Treat all named arguments as formulae.
      --ignore-dependencies        An unsupported Homebrew development flag to
                                   skip installing any dependencies of any kind.
                                   If the dependencies are not already present,
                                   the formula will have issues. If you're not
                                   developing Homebrew, consider adjusting your
                                   PATH rather than using this flag.
      --only-dependencies          Install the dependencies with specified
                                   options but do not install the formula
                                   itself.
      --cc                         Attempt to compile using the specified
                                   compiler, which should be the name of the
                                   compiler's executable, e.g. gcc-7 for GCC
                                   7. In order to use LLVM's clang, specify
                                   llvm_clang. To use the Apple-provided
                                   clang, specify clang. This option will only
                                   accept compilers that are provided by
                                   Homebrew or bundled with macOS. Please do not
                                   file issues if you encounter errors while
                                   using this option.
  -s, --build-from-source          Compile formula from source even if a
                                   bottle is provided. Dependencies will still
                                   be installed from bottles if they are
                                   available.
      --force-bottle               Install from a bottle if it exists for the
                                   current or newest version of macOS, even if
                                   it would not normally be used for
                                   installation.
      --include-test               Install testing dependencies required to run
                                   brew test formula.
      --HEAD                       If formula defines it, install the HEAD
                                   version, aka. main, trunk, unstable, master.
      --fetch-HEAD                 Fetch the upstream repository to detect if
                                   the HEAD installation of the formula is
                                   outdated. Otherwise, the repository's HEAD
                                   will only be checked for updates when a new
                                   stable or development version has been
                                   released.
      --keep-tmp                   Retain the temporary files created during
                                   installation.
      --debug-symbols              Generate debug symbols on build. Source will
                                   be retained in a cache directory. 
      --build-bottle               Prepare the formula for eventual bottling
                                   during installation, skipping any
                                   post-install steps.
      --bottle-arch                Optimise bottles for the specified
                                   architecture rather than the oldest
                                   architecture supported by the version of
                                   macOS the bottles are built on.
      --display-times              Print install times for each package at the
                                   end of the run.
  -i, --interactive                Download and patch formula, then open a
                                   shell. This allows the user to run
                                   ./configure --help and otherwise determine
                                   how to turn the software package into a
                                   Homebrew package.
  -g, --git                        Create a Git repository, useful for creating
                                   patches to the software.
      --overwrite                  Delete files that already exist in the prefix
                                   while linking.
      --cask, --casks              Treat all named arguments as casks.
      --[no-]binaries              Disable/enable linking of helper executables
                                   (default: enabled).
      --require-sha                Require all casks to have a checksum.
      --[no-]quarantine            Disable/enable quarantining of downloads
                                   (default: enabled).
      --skip-cask-deps             Skip installing cask dependencies.
      --zap                        For use with brew reinstall --cask. Remove
                                   all files associated with a cask. May remove
                                   files which are shared between applications.
      --appdir                     Target location for Applications (default:
                                   /Applications).
      --colorpickerdir             Target location for Color Pickers (default:
                                   ~/Library/ColorPickers).
      --prefpanedir                Target location for Preference Panes
                                   (default: ~/Library/PreferencePanes).
      --qlplugindir                Target location for QuickLook Plugins
                                   (default: ~/Library/QuickLook).
      --mdimporterdir              Target location for Spotlight Plugins
                                   (default: ~/Library/Spotlight).
      --dictionarydir              Target location for Dictionaries (default:
                                   ~/Library/Dictionaries).
      --fontdir                    Target location for Fonts (default:
                                   ~/Library/Fonts).
      --servicedir                 Target location for Services (default:
                                   ~/Library/Services).
      --input-methoddir            Target location for Input Methods (default:
                                   ~/Library/Input Methods).
      --internet-plugindir         Target location for Internet Plugins
                                   (default: ~/Library/Internet Plug-Ins).
      --audio-unit-plugindir       Target location for Audio Unit Plugins
                                   (default:
                                   ~/Library/Audio/Plug-Ins/Components).
      --vst-plugindir              Target location for VST Plugins (default:
                                   ~/Library/Audio/Plug-Ins/VST).
      --vst3-plugindir             Target location for VST3 Plugins (default:
                                   ~/Library/Audio/Plug-Ins/VST3).
      --screen-saverdir            Target location for Screen Savers (default:
                                   ~/Library/Screen Savers).
      --language                   Comma-separated list of language codes to
                                   prefer for cask installation. The first
                                   matching language is used, otherwise it
                                   reverts to the cask's default language. The
                                   default value is the language of your system.
  -q, --quiet                      Make some output more quiet.
  -h, --help                       Show this message.
Error: invalid option: --devel
(base) morozumikohei@MacBook-Air ~ % brew update 
brew upgrade
brew reinstall ethereum
Already up-to-date.
==> Upgrading 2 outdated packages:
postgresql@14 14.5 -> 14.5_1
heroku/brew/heroku 7.62.0 -> 7.63.0
==> Downloading https://ghcr.io/v2/homebrew/core/postgresql/14/manifests/14.5_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/postgresql/14/blobs/sha256:1f51
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sh
######################################################################## 100.0%
==> Downloading https://cli-assets.heroku.com/heroku-v7.63.0/heroku-v7.63.0.tar.
######################################################################## 100.0%
==> Upgrading postgresql@14
  14.5 -> 14.5_1 

==> Pouring postgresql@14--14.5_1.monterey.bottle.tar.gz
==> Caveats
Previous versions of postgresql shared the same data directory.

You can migrate to a versioned data directory by running:
  mv -v "/usr/local/var/postgres" "/usr/local/var/postgresql@14"

(Make sure PostgreSQL is stopped before executing this command)

This formula has created a default database cluster with:
  initdb --locale=C -E UTF-8 /usr/local/var/postgres
For more details, read:
  https://www.postgresql.org/docs/14/app-initdb.html

To restart postgresql@14 after an upgrade:
  brew services restart postgresql@14
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/postgresql@14/bin/postgres -D /usr/local/var/postgres
==> Summary
🍺  /usr/local/Cellar/postgresql@14/14.5_1: 3,309 files, 44.4MB
==> Running `brew cleanup postgresql@14`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /usr/local/Cellar/postgresql@14/14.5... (3,309 files, 44.4MB)
Warning: Directory not empty @ dir_s_rmdir - /usr/local/Cellar/postgresql@14/14.5
Removing: /usr/local/Cellar/postgresql/14.5... (3,307 files, 44.4MB)
Warning: Directory not empty @ dir_s_rmdir - /usr/local/Cellar/postgresql/14.5
==> Upgrading heroku/brew/heroku
  7.62.0 -> 7.63.0 

Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/heroku
Target /usr/local/bin/heroku
already exists. You may want to remove it:
  rm '/usr/local/bin/heroku'

To force the link and overwrite all conflicting files:
  brew link --overwrite heroku

To list all files that would be deleted:
  brew link --overwrite --dry-run heroku

Possible conflicting files are:
/usr/local/bin/heroku -> /usr/local/lib/heroku/bin/heroku
==> Caveats
To use the Heroku CLI's autocomplete --
  Via homebrew's shell completion:
    1) Follow homebrew's install instructions https://docs.brew.sh/Shell-Completion
        NOTE: For zsh, as the instructions mention, be sure compinit is autoloaded
              and called, either explicitly or via a framework like oh-my-zsh.
    2) Then run
      $ heroku autocomplete --refresh-cache
  OR
  Use our standalone setup:
    1) Run and follow the install steps:
      $ heroku autocomplete

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/heroku/7.63.0: 36,083 files, 83.9MB, built in 2 minutes 58 seconds
==> Running `brew cleanup heroku`...
Removing: /usr/local/Cellar/heroku/7.62.0... (36,083 files, 83.9MB)
Removing: /Users/morozumikohei/Library/Caches/Homebrew/heroku--7.62.0.tar.xz... (9.3MB)
==> Caveats
==> postgresql@14
Previous versions of postgresql shared the same data directory.

You can migrate to a versioned data directory by running:
  mv -v "/usr/local/var/postgres" "/usr/local/var/postgresql@14"

(Make sure PostgreSQL is stopped before executing this command)

This formula has created a default database cluster with:
  initdb --locale=C -E UTF-8 /usr/local/var/postgres
For more details, read:
  https://www.postgresql.org/docs/14/app-initdb.html

To restart postgresql@14 after an upgrade:
  brew services restart postgresql@14
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/postgresql@14/bin/postgres -D /usr/local/var/postgres
==> heroku
To use the Heroku CLI's autocomplete --
  Via homebrew's shell completion:
    1) Follow homebrew's install instructions https://docs.brew.sh/Shell-Completion
        NOTE: For zsh, as the instructions mention, be sure compinit is autoloaded
              and called, either explicitly or via a framework like oh-my-zsh.
    2) Then run
      $ heroku autocomplete --refresh-cache
  OR
  Use our standalone setup:
    1) Run and follow the install steps:
      $ heroku autocomplete

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Downloading https://ghcr.io/v2/homebrew/core/ethereum/manifests/1.10.23
Already downloaded: /Users/morozumikohei/Library/Caches/Homebrew/downloads/13a6ea65be43d649aab6e0f9426e46805ef9f7c1a605e81518ea7d7610380f98--ethereum-1.10.23.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/ethereum/blobs/sha256:173919306
Already downloaded: /Users/morozumikohei/Library/Caches/Homebrew/downloads/feb891514d4c7bf7d2ea33f6e1389cb4ff7e3194d39979eb878043a19bce705e--ethereum--1.10.23.monterey.bottle.tar.gz
==> Reinstalling ethereum 
==> Pouring ethereum--1.10.23.monterey.bottle.tar.gz
🍺  /usr/local/Cellar/ethereum/1.10.23: 19 files, 197.8MB
==> Running `brew cleanup ethereum`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
```

とりあえずインストールっぽいバーが出て、最新版に切り替わったっぽいので次に進みました。

# 1-2. ノード用の準備

次に、ディレクトリの作成です。次を実行しました。

```
 mkdir reality/node01 reality/node02 reality/node03 reality/node04
```

結果はこちら。

```
mkdir: reality: No such file or directory
mkdir: reality: No such file or directory
mkdir: reality: No such file or directory
mkdir: reality: No such file or directory
```

こんな基礎的なことでもエラーを出してしまうのが初心者ゆえの過ち。早速、似た事例を「mkdir エラー」でググってみると以下の記事が見つかりました。

https://qiita.com/web-hackers/items/e6cf2b222fc035ee6766#:~:text=mkdirは作成しようとしているディレクトリが存在していると、エラーになりディレクトリが作成されない%E3%80%82,ディレクトリがすでにあるにもかかわらず再度作成すると、そのディレクトリ内容も削除されてしまうからです%E3%80%82%20また、mkdirは作成する親ディレクトリが存在していなくてもエラーになり子ディレクトリが作成されません%E3%80%82

なるほど〜mkdirはーpオプションを使わないとエラーが出ることもあるのか、ということを知って、次のコードを実行しました。

```
mkdir -p reality/node01 reality/node02 reality/node03 reality/node04
```

対象のディレクトリを調べてみると…

![スクリーンショット 2022-09-02 22.07.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/3836472d-9f1f-7a26-9cc3-b79cf193649b.png)

できてました！

次はgenesis blockというブロックチェーンの革新っぽいことをやりますが、いきなりそんな単語が来て「作成する」と説明されてもわからないのが初心者の所以（n回目）。というわけで「genesis block」とGoogle先生に聞いてみます。すると…

https://ailog.site/2021/06/23/2021/0623/

まあ、当たり前といえば当たり前ですが、下のコードを書いてjsonファイルで保存するということでしょうね。

Visual Studio Codeで下のコードを書いてファイルを作成しました。

```genesis.json
{
  "config": {
    "chainId": 15,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "ethash": {}
  },
  "difficulty": "1",
  "gasLimit": "8000000",
  "alloc": {
    "7df9a875a174b3bc565e6424a0050ebc1b2d1d82": { "balance": "300000" },
    "f41c74c9ae680c1aa78f42e5647a62f353b7bdde": { "balance": "400000" }
  }
}
```

このファイルをrealityの中に移動させます。

そして、下のコードをターミナルで実行します。

```
geth init --datadir reality/node01 reality/genesis.json
```

実行結果はこちらです。

```
INFO [09-02|22:29:44.743] Maximum peer count                       ETH=50 LES=0 total=50
INFO [09-02|22:29:44.749] Set global gas cap                       cap=50,000,000
INFO [09-02|22:29:44.751] Allocated cache and file handles         database=/Users/morozumikohei/reality/node01/geth/chaindata cache=16.00MiB handles=16
INFO [09-02|22:29:44.994] Opened ancient database                  database=/Users/morozumikohei/reality/node01/geth/chaindata/ancient/chain readonly=false
INFO [09-02|22:29:44.994] Writing custom genesis block 
INFO [09-02|22:29:44.995] Persisted trie from memory database      nodes=3 size=397.00B time="476.491µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-02|22:29:44.998] Successfully wrote genesis state         database=chaindata hash=c3638c..f97051
INFO [09-02|22:29:44.998] Allocated cache and file handles         database=/Users/morozumikohei/reality/node01/geth/lightchaindata cache=16.00MiB handles=16
INFO [09-02|22:29:45.204] Opened ancient database                  database=/Users/morozumikohei/reality/node01/geth/lightchaindata/ancient/chain readonly=false
INFO [09-02|22:29:45.204] Writing custom genesis block 
INFO [09-02|22:29:45.205] Persisted trie from memory database      nodes=3 size=397.00B time="375.752µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-02|22:29:45.206] Successfully wrote genesis state         database=lightchaindata hash=c3638c..f97051
```

Successfullyと出ているので、まあ、多分、大丈夫でしょう。

2~4のファイルにも同じように実行させます。

```
geth init --datadir reality/node02/ reality/genesis.json
geth init --datadir reality/node03/ reality/genesis.json
geth init --datadir reality/node04/ reality/genesis.json
```

上と同じように実行できました。1行ずつ進めていきましょう。

# 1-3. ノードを起動する

いよいよノードを起動させる段階のようです。

まず、下のコードを実行しました。

```
geth --datadir reality/node01 --networkid 15 --http --http.addr [YOUR_LOCAL_IP] --http.port 8101 --http.vhosts=*
```

ここで、下の記事を参考にローカルIPアドレスを調べて、YOUR_LOCAL_IPに代入しました。

https://tamoc.com/local-ip-address/

しかし、次のようなエラーが出てしまいました。

```
zsh: no matches found: [YOUR_LOCAL_IP]
```

zshが見つからないとのことで、PATHが通ってないと最初思われました。

https://qiita.com/k3ntar0/items/eb8cdbd8eba9da388def

ただ、もう少し調べるとglob表現が引っかかっているように思いました。

https://qiita.com/nisaji/items/f9eede2164a74bc08db7

https://shirusu-ni-tarazu.hatenablog.jp/entry/2013/01/18/034233

というわけで、.zshrcに

```
setopt nonomatch
```

と書けば良いとのこと。

ただ、zshrcとはなんぞ？というレベルなので調べました。

zshrcは、zshの設定ファイルです。

https://qiita.com/d-dai/items/d7f329b7d82e2165dab3

そして、zshはシェルの一種です。

https://qiita.com/d-dai/items/084cace7f6bfd3580f9d

そしてそして、シェルとはOSとのインターフェースです。

https://mo-gu-mo-gu.com/what-is-shell/#:~:text=シェルとは、%20OSとのインターフェイスを提供するアプリケーション%20のことです%E3%80%82%20ユーザーの,命令を解釈しOSに伝え%20、%20OSの結果をユーザーに返却する%20役割があります%E3%80%82

https://recruit.cct-inc.co.jp/tecblog/os/shell/

多分、この辺りの記事を読んでターミナルをこの機会に徹底理解するのが良いだろう。

https://qiita.com/kinchiki/items/57e9391128d07819c321

https://qiita.com/fischeri_phys/items/4443807a18dfc990e6d8

（編集追記）

ターミナルの調整はできたが、1-3以降、マイニングのエラーは防げるようになってもメタマスクとの連携がうまくいかなかったり、ターミナル上でのIPアドレスの謎の衝突が起きたり、とにかくトラブルが続いて解決には至らなかった。一応、いくつか解けたエラーの対策は備忘録的に列挙しておく。

まず、以降のNFT化に必要なサーバーに画像をアップするチュートリアル

https://qiita.com/bonchanri/items/e04c0685f766a3395c6f

https://snowsystem.net/development/web-server-simple-launch/#

次に、ターミナルで別タブを開こうとすると「already used」のエラーが出るので、バックグラウンドで実行するためのコマンド

https://kazmax.zpp.jp/linux_beginner/process_background.html

https://shikiyura.com/2018/07/%E3%80%90linux-mac%E3%80%91%E3%83%90%E3%83%83%E3%82%AF%E3%82%B0%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%E3%81%AE%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E3%83%AD%E3%82%B0%E3%82%A2%E3%82%A6%E3%83%88%E5%BE%8C/

TCP/IP、ポート番号周りの基礎知識

https://atmarkit.itmedia.co.jp/ait/articles/0610/14/news021.html

https://time-space.kddi.com/ict-keywords/20200930/2984

https://www.nic.ad.jp/ja/basics/terms/port-number.html

メタマスクが繋がらない時のRPCのエラー対応

https://sakuya-chips.com/628/

チェーン情報一覧

https://espo-game.jp/article/blockchain-game/metamask/91520/

ターミナルで

```
Fatal: Error starting protocol stack: listen tcp 127.0.0.1:8551: bind: address already in use
```

のエラーが出て（自分はアホみたいに悩んで三週間くらい詰まった）動いているプロセスを特定して切断する方法

https://teratail.com/questions/320011

https://qiita.com/kyons/items/f2b627440073548bcd6b

海外でも似たようなエラーで結構苦しんでいる人がいた

https://github.com/ethereum/go-ethereum/issues/1271

teratailで相談した。redditの/r/miningとか（正式名称は忘れた）で質問投稿したら出禁になっちった。。。（ウォレットを聞き出そうとするDMが届いたりした笑）

https://teratail.com/questions/0j5uzdwj3jwcdy

mentaでもブロックチェーンに強そうな人に対応できるか相談したけど返事が来ないので無理そう。

というわけで、1-4以降、あるいは4-4以降のメタマスクがらみでつまづいてしまった。

ひとまず別のチュートリアルに取り組みながら、またレベルアップした段階で取り組もうと思います。