Open39

IPFS Kubo を試してみる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Hello Kubo

準備コマンド
mkdir hello-kubo
cd hello-kubo
mkdir -p export data/ipfs
touch start-ipfs-node.sh
start-ipfs-node.sh
docker run -d \
  --name ipfs_host \
  -v `pwd`/export:/export \
  -v `pwd`/data/ipfs:/data/ipfs \
  -p 4001:4001 \
  -p 4001:4001/udp \
  -p 127.0.0.1:8080:8080 \
  -p 127.0.0.1:5001:5001 \
  ipfs/kubo:latest
起動コマンド
source start-ipfs-node.sh
docker logs -f ipfs_host
実行結果
Changing user to ipfs
ipfs version 0.18.0
generating ED25519 keypair...done
peer identity: 12D3KooWN7ZWvXbvnDBR6hjq44MpgqVXv44Kg41SQjLxEDAVC3Xn
initializing IPFS node at /data/ipfs
to get started, enter:

	ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme

Initializing daemon...
Kubo version: 0.18.0-6750377
Repo version: 13
System version: amd64/linux
Golang version: go1.19.1

Computing default go-libp2p Resource Manager limits based on:
    - 'Swarm.ResourceMgr.MaxMemory': "2.1 GB"
    - 'Swarm.ResourceMgr.MaxFileDescriptors': 524288

Applying any user-supplied overrides on top.
Run 'ipfs swarm limit all' to see the resulting limits.

2023/01/24 07:47:22 failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/127.0.0.1/udp/4001/quic
Swarm listening on /ip4/127.0.0.1/udp/4001/quic-v1
Swarm listening on /ip4/127.0.0.1/udp/4001/quic-v1/webtransport/certhash/uEiBQSQNk2waz5Qhsbi-SDT2-uj1JWhxQJEja0yPGTcg7MQ/certhash/uEiC5cQtGdmYslVmXi0xhPlUUByUviUdj5isFc69F_QWKHw
Swarm listening on /ip4/172.17.0.2/tcp/4001
Swarm listening on /ip4/172.17.0.2/udp/4001/quic
Swarm listening on /ip4/172.17.0.2/udp/4001/quic-v1
Swarm listening on /ip4/172.17.0.2/udp/4001/quic-v1/webtransport/certhash/uEiBQSQNk2waz5Qhsbi-SDT2-uj1JWhxQJEja0yPGTcg7MQ/certhash/uEiC5cQtGdmYslVmXi0xhPlUUByUviUdj5isFc69F_QWKHw
Swarm listening on /p2p-circuit
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/127.0.0.1/udp/4001/quic
Swarm announcing /ip4/127.0.0.1/udp/4001/quic-v1
Swarm announcing /ip4/127.0.0.1/udp/4001/quic-v1/webtransport/certhash/uEiBQSQNk2waz5Qhsbi-SDT2-uj1JWhxQJEja0yPGTcg7MQ/certhash/uEiC5cQtGdmYslVmXi0xhPlUUByUviUdj5isFc69F_QWKHw
Swarm announcing /ip4/172.17.0.2/tcp/4001
Swarm announcing /ip4/172.17.0.2/udp/4001/quic
Swarm announcing /ip4/172.17.0.2/udp/4001/quic-v1
Swarm announcing /ip4/172.17.0.2/udp/4001/quic-v1/webtransport/certhash/uEiBQSQNk2waz5Qhsbi-SDT2-uj1JWhxQJEja0yPGTcg7MQ/certhash/uEiC5cQtGdmYslVmXi0xhPlUUByUviUdj5isFc69F_QWKHw
Swarm announcing /ip4/202.208.152.34/udp/59081/quic
API server listening on /ip4/0.0.0.0/tcp/5001
WebUI: http://0.0.0.0:5001/webui
Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080
Daemon is ready
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

IPFS コマンド実行

docker exec ipfs_host ipfs <args...>

下記は接続しているピアを一覧表示するコマンド

docker exec ipfs_host ipfs swarm peers

下記のような行が何十件も表示される

/ip4/123.123.123.123/tcp/4001/p2p/12D3KooWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ファイルの追加

ファイルの追加コマンド
echo 'Hello IPFS!' > export/message.txt
docker exec ipfs_host ipfs add -r /export/message.txt
実行結果
 12 B / 12 B  100.00%added QmYWAifyw2V5dEq7c5GgdSPffeKoYXQZggnYzw5RbXpig4 message.txt

追加したファイルはどうやって見れば良いのだろうか

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

IPFS ノードを server プロファイルで起動する

環境変数 IPFS_PROFILE を "server" に指定すれば良い

start-ipfs-node.sh
docker run -d \
  --name ipfs_host \
  -e IPFS_PROFILE=server \
  -v `pwd`/export:/export \
  -v `pwd`/data/ipfs:/data/ipfs \
  -p 4001:4001 \
  -p 4001:4001/udp \
  -p 127.0.0.1:8080:8080 \
  -p 127.0.0.1:5001:5001 \
  ipfs/kubo:latest

せっかくなので初期化してみる

docker stop ipfs_host
docker rm ipfs_host
rm -rf data
mkdir -p data/ipfs
source start-ipfs-node.sh
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

IPFS Kubo Tutorial

https://docs.ipfs.tech/how-to/command-line-quick-start/

実行コマンド
docker exec ipfs_host \
  ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
実行結果
Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| Warning:                                              |
|   This is alpha software. Use at your own discretion! |
|   Much is missing or lacking polish. There are bugs.  |
|   Not yet secure. Read the security notes for more.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Quick Start も見てみる

実行コマンド
docker exec ipfs_host \
  ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/quick-start
実行結果
# 0.1 - Quick Start

This is a set of short examples with minimal explanation. It is meant as
a "quick start".


Add a file to ipfs:

  echo "hello world" >hello
  ipfs add hello


View it:

  ipfs cat <the-hash-you-got-here>


Try a directory:

  mkdir foo
  mkdir foo/bar
  echo "baz" > foo/baz
  echo "baz" > foo/bar/baz
  ipfs add -r foo


View things:

  ipfs ls <the-hash-here>
  ipfs ls <the-hash-here>/bar
  ipfs cat <the-hash-here>/baz
  ipfs cat <the-hash-here>/bar/baz
  ipfs cat <the-hash-here>/bar
  ipfs ls <the-hash-here>/baz


References:

  ipfs refs <the-hash-here>
  ipfs refs -r <the-hash-here>
  ipfs refs --help


Get:

  ipfs get <the-hash-here> -o foo2
  diff foo foo2


Objects:

  ipfs object get <the-hash-here>
  ipfs object get <the-hash-here>/foo2
  ipfs object --help


Pin + GC:

  ipfs pin add <the-hash-here>
  ipfs repo gc
  ipfs ls <the-hash-here>
  ipfs pin rm <the-hash-here>
  ipfs repo gc


Daemon:

  ipfs daemon  (in another terminal)
  ipfs id


Network:

  (must be online)
  ipfs swarm peers
  ipfs id
  ipfs cat <hash-of-remote-object>


Mount:

  (warning: fuse is finicky!)
  ipfs mount
  cd /ipfs/<the-hash-here>
  ls


Tool:

  ipfs version
  ipfs update
  ipfs commands
  ipfs config --help
  open http://localhost:5001/webui


Browse:

  WebUI:

    http://localhost:5001/webui

  video:

    http://localhost:8080/ipfs/QmVc6zuAneKJzicnJpfrqCH9gSy6bz54JhcypfJYhGUFQu/play#/ipfs/QmTKZgRNwDNZwHtJSjCp6r5FYefzpULfy37JvMt9DwvXse

  images:

    http://localhost:8080/ipfs/QmZpc3HvfjEXvLWGQPWbHk3AjD5j8NEN4gmFN8Jmrd5g83/cs

  markdown renderer app:

    http://localhost:8080/ipfs/QmX7M9CiYXjVeFnkfVGf3y5ixTZ2ACeSGyL1vBJY1HvQPp/mdown
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

オブジェクトの取得

実行コマンド
docker exec ipfs_host \
  ipfs cat /ipfs/QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq > export/spaceship-launch.jpg

リダイレクトは docker プロセスに対して行われるので /export ではなくて export を指定する

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ファイルが見つからない場合

ハングアップしているような状態になる

docker exec ipfs_host \
  ipfs cat /ipfs/QmQPk9Vi9iSm4aAPEd73txGjqwbHhLYWfoUEpG5eYmy2PW
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ファイルの追加

Hello IPFS!
追加コマンド
docker exec ipfs_host ipfs add -q /export/message.txt
確認コマンド
docker exec ipfs_host \
  ipfs cat /ipfs/QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk
確認結果
Hello IPFS!
curlを使った確認コマンド
curl https://ipfs.io/ipfs/QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk
確認結果
Hello IPFS!

タイミングが悪いと 429 Too Many Requests が発生する

429_Too_Many_Requests
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>openresty</center>
</body>
</html>
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

MFS へのコピー

IPFS では MFS (Mutable FileSystem) というものがあり、MFS を使うと普通の名前付きファイルシステムのようにデータを管理できる

IPFS に追加したファイルを MFS へコピーするには下記のコマンドを実行する

docker exec ipfs_host \
  ipfs files cp /ipfs/QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk /dest

MFS にコピーされたファイルは Web UI の Files ページに表示される

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ディレクトリの追加を試してみる

ディレクトリ追加コマンド
mkdir export/foo
mkdir export/foo/bar
echo "baz" > export/foo/baz
echo "baz" > export/foo/bar/baz
docker exec ipfs_host ipfs add -r /export/foo
実行結果
 4 B / 8 B   50.00%added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bar/baz
 8 B / 8 B  100.00%added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/baz
added QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN foo/bar
 8 B / 8 B  100.00%added QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm foo
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ディレクトリに ls や cat を試してみる

実行コマンド
docker exec ipfs_host ipfs ls QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
実行結果
QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN - bar/
QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 4 baz

そういえば CID の前に /ipfs/ はいらないのだろうか

実行コマンド
docker exec ipfs_host ipfs cat QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
実行結果
Error: this dag node is a directory

ディレクトリを cat しようとするとエラーになる

$ docker exec ipfs_host ipfs ls QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR
$

ファイルを ls しても何も表示されない

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Refs とは何か?

$ docker exec ipfs_host ipfs refs -h
USAGE
  ipfs refs <ipfs-path>... - List links (references) from an object.

  ipfs refs [--format=<format>] [--edges | -e] [--unique | -u]
            [--recursive | -r] [--max-depth=<max-depth>] [--] <ipfs-path>...

  Lists the hashes of all the links an IPFS or IPNS object(s) contains,
  with the following format:
  
    <link base58 hash>
  
  List all references recursively by using the flag '-r'.
  
  NOTE: Like most other commands, Kubo will try to fetch the blocks of the passed path if they can't be found in the local store if it is running in online mode.

SUBCOMMANDS
  ipfs refs local - List all local references.

  For more information about each command, use:
  'ipfs refs <subcmd> --help'

ディレクトリに含まれるファイルの CID を一覧表示することらしい

$ docker exec ipfs_host ipfs refs QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN
QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

オブジェクトのダウンロード

オブジェクトを一気にダウンロードしたいときは ipfs get が便利そう

$ docker exec ipfs_host ipfs get -h
USAGE
  ipfs get <ipfs-path> - Download IPFS objects.

  ipfs get [--output=<output> | -o] [--archive | -a] [--compress | -C]
           [--compression-level=<compression-level> | -l] [--progress=false]
           [--] <ipfs-path>

  Stores to disk the data contained an IPFS or IPNS object(s) at the given path.
  
  By default, the output will be stored at './<ipfs-path>', but an alternate
  path can be specified with '--output=<path>' or '-o=<path>'.
  
  To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
  
  To compress the output with GZIP compression, use '--compress' or '-C'. You
  may also specify the level of compression by specifying '-l=<1-9>'.

  For more information about each command, use:
  'ipfs get <subcmd> --help'

試してみる

$ docker exec ipfs_host \
  ipfs get QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm \
  -o /export/foo2
Saving file(s) to /export/foo2
 167 B / 167 B  100.00% 0s
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ipfs object は deprecated

$ docker exec ipfs_host ipfs object -h
WARNING:   DEPRECATED, command will be removed in the future

USAGE
  ipfs object - Deprecated commands to interact with dag-pb objects. Use 'dag'
                or 'files' instead.

  ipfs object

  'ipfs object' is a legacy plumbing command used to manipulate dag-pb objects
  directly. Deprecated, use more modern 'ipfs dag' and 'ipfs files' instead.

  For more information about each command, use:
  'ipfs object <subcmd> --help'

DEPRECATED SUBCOMMANDS
  ipfs object data <key>           - Deprecated way to read the raw bytes of a
                                     dag-pb object: use 'dag get' instead.
  ipfs object diff <obj_a> <obj_b> - Display the diff between two IPFS objects.
  ipfs object get <key>            - Deprecated way to get and serialize the
                                     dag-pb node. Use 'dag get' instead
  ipfs object links <key>          - Deprecated way to output links in the
                                     specified dag-pb object: use 'dag get'
                                     instead.
  ipfs object new [<template>]     - Deprecated way to create a new dag-pb
                                     object from a template.
  ipfs object patch                - Deprecated way to create a new merkledag
                                     object based on an existing one. Use MFS
                                     with 'files cp|rm' instead.
  ipfs object put <data>           - Deprecated way to store input as a DAG
                                     object. Use 'dag put' instead.
  ipfs object stat <key>           - Deprecated way to read stats for the
                                     dag-pb node. Use 'files stat' instead.

今日はこの辺りにしておこう

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ピン

$ docker exec ipfs_host ipfs pin -h
USAGE
  ipfs pin - Pin (and unpin) objects to local storage.

  ipfs pin

SUBCOMMANDS
  ipfs pin add <ipfs-path>...           - Pin objects to local storage.
  ipfs pin ls [<ipfs-path>]...          - List objects pinned to local storage.
  ipfs pin remote                       - Pin (and unpin) objects to remote
                                          pinning service.
  ipfs pin rm <ipfs-path>...            - Remove object from pin-list.
  ipfs pin update <from-path> <to-path> - Update a recursive pin.
  ipfs pin verify                       - Verify that recursive pins are
                                          complete.

  For more information about each command, use:
  'ipfs pin <subcmd> --help'
$ docker exec ipfs_host ipfs pin ls
QmQGiYLVAdSHJQKYFRTJZMG4BXBHqKperaZtyKGmCRLmsF indirect
QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc recursive
QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR indirect
QmYCvbfNbCwFR45HiNP45rwJgvatpiW38D961L5qAhUM5Y indirect
QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk recursive
QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm recursive
QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB indirect
QmQy6xmJhrcC5QLboAcGFcAE1tC8CrwDVkrHdEYJkLscrQ indirect
QmU5k7ter3RdjZXu3sHghsga1UQtrztnQxmTL22nPnsu3g indirect
QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN indirect
QmejvEPop4D7YUadeGqYWmZxHhLc4JBUCzJJHWMzdcMe2y indirect
QmQ5vhrL7uv6tuoN9KeVBwd4PwfQkXdVVmDLUZuTNxqgvm indirect

まだ何もピンしていないのにピンされているオブジェクトがある

ipfs catipfs ls で中身を見たところ、これまでに cat したりして見たファイルやディレクトリのようだ

$ docker exec ipfs_host ipfs pin add -h
USAGE
  ipfs pin add <ipfs-path>... - Pin objects to local storage.

  ipfs pin add [--recursive=false] [--progress] [--] <ipfs-path>...

  Stores an IPFS object(s) from a given path locally to disk.

  For more information about each command, use:
  'ipfs pin add <subcmd> --help'

BAYC のトークン番号 0 の画像データをピンしてみる

https://gateway.pinata.cloud/ipfs/QmRRPWG96cmgTn2qSzjwr2qvfNEuhunv6FNeMFGa9bx6mQ

$ docker exec ipfs_host ipfs pin add QmRRPWG96cmgTn2qSzjwr2qvfNEuhunv6FNeMFGa9bx6mQ
pinned QmRRPWG96cmgTn2qSzjwr2qvfNEuhunv6FNeMFGa9bx6mQ recursively
$ docker exec ipfs_host ipfs pin ls QmRRPWG96cmgTn2qSzjwr2qvfNEuhunv6FNeMFGa9bx6mQ

recursively とあるがファイルなのに関係あるのだろうか

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ガベージコレクション

$ docker exec ipfs_host ipfs repo -h
USAGE
  ipfs repo - Manipulate the IPFS repo.

  ipfs repo

  'ipfs repo' is a plumbing command used to manipulate the repo.

SUBCOMMANDS
  ipfs repo gc      - Perform a garbage collection sweep on the repo.
  ipfs repo ls      - List all local references.
  ipfs repo migrate - Apply any outstanding migrations to the repo.
  ipfs repo stat    - Get stats for the currently used repo.
  ipfs repo verify  - Verify all blocks in repo are not corrupted.
  ipfs repo version - Show the repo version.

  For more information about each command, use:
  'ipfs repo <subcmd> --help'

DEPRECATED SUBCOMMANDS
  ipfs repo fsck - Remove repo lockfiles.
$ docker exec ipfs_host ipfs repo stat
NumObjects: 5973
RepoSize:   41839023
StorageMax: 10000000000
RepoPath:   /data/ipfs
Version:    fs-repo@13
$ docker exec ipfs_host ipfs repo gc
removed bafkreias34q5t2mvly2f4v5xwn5pvprt5wvezxox36plzgu3umyelwg5na
removed bafkreicjwu5ym6256guny7jlxmgilxdiwkdnbuqme5jqyczxcxvdnmq5na
removed bafkreibn3wvv7pni64ukvm4w4jm2hlzylw4zvvrl4qiuh3vtpvzn4xv5n4
... (全部で6366件が削除された様子)
$ docker exec ipfs_host ipfs repo stat
NumObjects: 931
RepoSize:   789814
StorageMax: 10000000000
RepoPath:   /data/ipfs
Version:    fs-repo@13

Web UI からも減っている様子がわかる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ブロックについて

ファイルが 256 KiB 以上だとブロックに分割される

$ docker exec ipfs_host \
  ipfs ls QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq
QmdXmL2dyFU5ZT51G7bXzc3D1sPaBLEJiQtDRgzDhEAwx1 262144 
QmUfYrWyvRbdJVpUfp3A7oCKBf13uLouaJ3VBMZtkBnb5b 14238

1つ目の方にアクセスすると同じような画像が表示される

2つ目の方にアクセスするとバイナリデータがダウンロードされる

調べてみると1つ目の方のサイズは 262,144 Byte = 256 KiB だった

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Block 操作

ipfs block get コマンドを実行するとブロック生データをバイナリで取得できる

$ docker exec ipfs_host \
  ipfs block get QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq 
*
" ?-d????-~F?X)??m???_?X_?????)
" ]??d!5 Npѐ ?O(z<?V޿#?:@`ʹ?o
?? ?? ?o

ipfs object linksipfs ls と同等

$ docker exec ipfs_host \
  ipfs object links QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq
QmdXmL2dyFU5ZT51G7bXzc3D1sPaBLEJiQtDRgzDhEAwx1 262158 
QmUfYrWyvRbdJVpUfp3A7oCKBf13uLouaJ3VBMZtkBnb5b 14249 
$ docker exec ipfs_host \
  ipfs ls QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq      
QmdXmL2dyFU5ZT51G7bXzc3D1sPaBLEJiQtDRgzDhEAwx1 262144 
QmUfYrWyvRbdJVpUfp3A7oCKBf13uLouaJ3VBMZtkBnb5b 14238  

ハッシュだけが必要な場合は ipfs refs の方が良い

$ docker exec ipfs_host ipfs refs QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq
QmdXmL2dyFU5ZT51G7bXzc3D1sPaBLEJiQtDRgzDhEAwx1
QmUfYrWyvRbdJVpUfp3A7oCKBf13uLouaJ3VBMZtkBnb5b
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ブロックとオブジェクトは違うのかな?

$ echo "This is some data" | docker exec -i ipfs_host ipfs block put
bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
$ docker exec ipfs_host \
  ipfs block get bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
This is some data
$ docker exec ipfs_host \
  ipfs cat bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
This is some data

一方 ipfs add を使う場合

$ echo "This is some data" | docker exec -i ipfs_host ipfs add                                                                   
 18 B / ? added Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4 Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4
 18 B / 18 B  100.00%
$ docker exec -i ipfs_host \
  ipfs cat Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4
This is some data
$ docker exec -i ipfs_host \
  ipfs block get Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4

This is some data

今のところアドレスがちょっと違うくらいで違いがわからない

CID のバージョンが異なるので同じ内容なのかどうかはわからない

下記のコマンドを実行して変換できる

$ docker exec -i ipfs_host \
  ipfs cid format -v 1 -b base32 Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4
bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm

ga で終わるものとは違うブロックが出てきた

まずは tm で終わる方(ipfs add した方)を色々と探ってみる

$ docker exec -i ipfs_host \
  ipfs refs bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
$ docker exec -i ipfs_host \
  ipfs cat bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
This is some data
$ docker exec -i ipfs_host \
  ipfs block get bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm

This is some data
$ docker exec -i ipfs_host \
  ipfs object stat bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
NumLinks:       0
BlockSize:      26
LinksSize:      2
DataSize:       24
CumulativeSize: 26
$ docker exec -i ipfs_host \
  ipfs dag get bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
{"Data":{"/":{"bytes":"CAISElRoaXMgaXMgc29tZSBkYXRhChgS"}},"Links":[]}

続いて ga で終わる方(ipfs block put した方)

$ docker exec -i ipfs_host \
  ipfs refs bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
$ docker exec -i ipfs_host \
  ipfs cat bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
This is some data
$ docker exec -i ipfs_host \
  ipfs block get bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
This is some data
$ docker exec -i ipfs_host \
  ipfs object stat bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga 
NumLinks:       0
BlockSize:      18
LinksSize:      0
DataSize:       18
CumulativeSize: 18
$ docker exec -i ipfs_host \
  ipfs dag get bafkreih5o5lixipg5nmhrerhlgphbgschpdw5ithq35vbkjjckxleyb7ga
{"/":{"bytes":"VGhpcyBpcyBzb21lIGRhdGEK"}}

同じ内容なのに別のブロックとして表現されるのが興味深い

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ipfs コマンドを使って Pinata にピンしてみる

https://docs.pinata.cloud/pinata-api/pinning-services-api

$ docker exec -i ipfs_host \
  ipfs pin remote service add pinata https://api.pinata.cloud/psa <JWT>
$ docker exec -i ipfs_host \
  ipfs pin remote add --service pinata --name fromIpfsCommand Qmdi3Q6EZXusjMSRovDdVfnkroJnnwaburvb6deDbECDH4
Error: reason: "INVALID_ORIGINS", details: "provider array entry: /ip4/127.0.0.1/udp/4001/quic-v1/webtransport/certhash/uEiCB9bFQtPDdYcx3vN3qNNO_mSM3d9F-XFM_loTMTN2hwQ/certhash/uEiDAbWd55WlzsuYo968ZStHkfVCiokjzQjGEn6r1VfPQRw/p2p/12D3KooWPqZVUQP4fokXZ8za28nYxqZaMj1PHDCk1rKe97DeezgK is not a valid peer multiaddr": 400 Bad Request

エラーが表示されてピンできない、グローバル IP アドレスじゃないとダメなのかな?

そんなはずはないと思って色々やっていたらできた

  • Web UI のナビゲーションから SETTINGS を選んでクリック
  • IPFS Config の Addresses.Swarms からAddresses.NoAnnounce へ下記3点を移動
    • "/ip4/0.0.0.0/udp/4001/quic",
    • "/ip4/0.0.0.0/udp/4001/quic-v1",
    • "/ip4/0.0.0.0/udp/4001/quic-v1/webtransport"
  • docker stop ipfs_host && docker start ipfs_host で設定を反映
$ docker exec -i ipfs_host \
  ipfs pin remote add --service=pinata --name=byIpfsCommand bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
CID:    bafybeihelit6mpirtze5dmm45efbuizcwvj7aok63zr3d3fs5ocddl27tm
Name:   byIpfsCommand
Status: pinned

Pinata の My Files に表示された

変更した設定は一応元に戻しておこう

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ipfs mount できない

$ docker exec ipfs_host ipfs mount
Error: fuse failed to access mountpoint /ipfs

そろそろ Mac に IPFS をインストールする時だろうか

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

IPFS に Git レポジトリを保存する

コマンド
mkdir export/myrepo
cd export/myrepo
touch main.js
main.js
console.log("Hello, world!");
コマンド
git init
git add .
git commit -m "Initial commit"
cd ..
git clone --mirror myrepo myrepo2
cd myrepo2
git update-server-info
mv objects/pack/*.pack .
git unpack-objects < *.pack
rm -f *.pack objects/pack/*
docker exec ipfs_host ipfs add -r /export/data
実行結果
 21 B / ? added QmbRUdVtdtxcpdqyJE3iZwTJq7FPcXR1ErQRFB76sQCg9H myrepo2/HEAD
 252 B / ? added QmQGeJdtRfMAPiUGZyUwpofsMW73RyDm8VZJ5KGqYYkPuw myrepo2/config
 325 B / ? added Qmdy135ZFG4kUALkaMhr6Cy3VhhkxyAh264kyg3725x8be myrepo2/description
 803 B / ? added QmY2duvZ5Resxt8astYUgQ8RXQz1N9axe77gCb5j6M95Gf myrepo2/hooks/applypatch-msg.sample
 1.66 KiB / 23.91 KiB    6.94%added QmQbraCfKaCTZkqtdXCJPc11CWEiZGw1yYGwtbA6nbXWeh myrepo2/hooks/commit-msg.sample
 6.27 KiB / 23.91 KiB   26.24%added QmfUn9iq4rWKhKyzcdN9EG4HPDqnrgiWy1gZb7zuo33Bjo myrepo2/hooks/fsmonitor-watchman.sample
 6.46 KiB / 23.91 KiB   27.02%added QmQjYxVj9iwitDGkmR48Cemr1JTgc6pvwo5cFkumNWqnjm myrepo2/hooks/post-update.sample
 6.87 KiB / 23.91 KiB   28.75%added QmdzjzkpM31jTKd5YBJkWsbDXJeeW1Uy1UxVPwfKFxwy89 myrepo2/hooks/pre-applypatch.sample
 8.88 KiB / 23.91 KiB   37.16%added QmY33NoK9jzqitkPK1QdWTnNQt7m6DsE4fYvyohjdbyfju myrepo2/hooks/pre-commit.sample
 10.23 KiB / 23.91 KiB   42.77%added QmPte81MJoXgCngK75SVZTn2DAXskuo9gdVr2uR5PfVVQE myrepo2/hooks/pre-merge-commit.sample
added QmQVg6D9VT3Ro9JWnUYECobpTvVVh4hgz9jNEmXKEok1S9 myrepo2/hooks/pre-push.sample
 15.54 KiB / 23.91 KiB   65.00%added QmSQrei5kUrb4RaEp4c7oobLEHURhPJ8AFZS1uiRg4JfLv myrepo2/hooks/pre-rebase.sample
added QmRKbU9DFRNWjR1UwV4nC6MXPnrNanfsBM5579t4HLUuig myrepo2/hooks/pre-receive.sample
 17.00 KiB / 23.91 KiB   71.10%added QmPku8ai5p4sSCDHe19n9Ekfo21xM5urFdkq9Rg1wBHjcV myrepo2/hooks/prepare-commit-msg.sample
 23.28 KiB / 23.91 KiB   97.37%added Qma763g2HDRav2QxLaAEWKiyE42Z3e2vcojWThMzYNHyRq myrepo2/hooks/push-to-checkout.sample
added QmcV7YCAafpfa79M4Ys1Ffq4gbJEc8NukKxu4izEedgAno myrepo2/hooks/update.sample
 23.51 KiB / 23.91 KiB   98.35%added QmcfzxUpw36y8fu2GR3s7Vgq7RBgooKtc6BgsqFnadsDLc myrepo2/info/exclude
 23.70 KiB / 23.91 KiB   99.11%added QmVeWm24Pd8x3fCaWHCTFbyAtgTbuYmk8iDTn7mwHcNJcM myrepo2/info/refs
 23.71 KiB / 23.91 KiB   99.17%added QmYP9FYQhX7KqVSAUGdBW15V6fhZErnGPdrFjby3pHB4sv myrepo2/objects/02/700be738d125f3bbfb53fd3166ecff734b091b
 23.75 KiB / 23.91 KiB   99.36%added QmW6g1zwNU91L9rm8q3d6JUg43oRM5Y2QDy97kxLrQvPqK myrepo2/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
 23.81 KiB / 23.91 KiB   99.58%added QmZVqS7wcpJZgjSxWFVDM6toXZgRwAocGTydnuX53HuQBz myrepo2/objects/a8/141d3b18d3421ad3fd4ba372edf6e319252622
 23.81 KiB / 23.91 KiB   99.58%added QmbJJkyMpnaZy2hPbYhH9Q6LW2pA37oMYp9gsrMPEpV1EM myrepo2/objects/a9/ba3a185500c5abeca9db8dc0cb22fa314be10d
added Qmc5m94Gu7z62RC8waSKkZUrCCBJPyHbkpmGzEePxy2oXJ myrepo2/objects/info/packs
 23.91 KiB / 23.91 KiB  100.00%added QmVocythgPAprAkH3m3ZMnY8HvzdqKTjWppSRj57kENWka myrepo2/packed-refs
 23.91 KiB / 23.91 KiB  100.00%added QmbjKH6bppx7ce55qFt1AwSEpTmVJKYYPhbgAbsNNDh8LN myrepo2/hooks
added QmV1R83Y5HFi4RGRFdCY2oyESZbaunFXFAfyQ6mvrKxTFH myrepo2/info
added QmQTLLCURiMWeU1m7gBTzJmhbgYcHY4ZzbB8utYAj8jjjf myrepo2/objects/02
 23.91 KiB / 23.91 KiB  100.00%added QmTvqgarvbWaGa41HewF3GAexbHYsJ8Za3FH1JyAyaCiUZ myrepo2/objects/4b
 23.91 KiB / 23.91 KiB  100.00%added Qmei6r4htgvN2cf28MeF8dcFyGErqcDcaLzs3h1QV6B8bG myrepo2/objects/a8
 23.91 KiB / 23.91 KiB  100.00%added QmW1en8k7uDrWVoGoX2hvhyTqUVHaGucEarmWQBFzpnYLn myrepo2/objects/a9
added QmXaZFVFt87ZdXpuLbt1SLspjCFt89AN3Ec48cC7zZtnqt myrepo2/objects/info
added QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn myrepo2/objects/pack
added QmehSUbe6Hrx1xHKE8o3xPzsugqq48Kg1pktMyzRU3oNRD myrepo2/objects
 23.91 KiB / 23.91 KiB  100.00%added QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn myrepo2/refs/heads
 23.91 KiB / 23.91 KiB  100.00%added QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn myrepo2/refs/tags
added QmWYtSEta2Fzgy4u4ttdwwiKMUikwZrFHxa5quWXMVyBhy myrepo2/refs
added QmPs2Fd7Pe6TB1xSykbXkzzrMVan6ssD65MEefzDMJjwfh myrepo2
コマンド
git clone http://localhost:8080/ipfs/QmPs2Fd7Pe6TB1xSykbXkzzrMVan6ssD65MEefzDMJjwfh myrepo3
cat myrepo3/main.js
実行結果
console.log("Hello, world!");

どういう場面で使えば良いだろう

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

IPNS を使ってみる

コマンド
$ docker exec ipfs_host ipfs add /export/message.txt
added QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk message.txt
 11 B / 11 B [=========================================================] 100.00%
$ docker exec ipfs_host ipfs name publish QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk
Published to k51qzi5uqu5dldi96bmpio1vdb0rabo26tgwinhced3es3gkni0p71fv0pr1tw: /ipfs/QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk

コマンド
touch export/new-message.txt
export/new-message.txt
Hello IPFS! by tatsuyasusukida
コマンド
$ docker exec ipfs_host ipfs add /export/new-message.txt
 30 B / ? added QmSRwmAKDKBr7Ba3vfpbncnrngYBM9s2ZGnqRcnc9FLbg4 new-message.txt
 30 B / 30 B  100.00%
$ docker exec ipfs_host ipfs name publish QmSRwmAKDKBr7Ba3vfpbncnrngYBM9s2ZGnqRcnc9FLbg4
Published to k51qzi5uqu5dldi96bmpio1vdb0rabo26tgwinhced3es3gkni0p71fv0pr1tw: /ipfs/QmSRwmAKDKBr7Ba3vfpbncnrngYBM9s2ZGnqRcnc9FLbg4
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Fleek を試してみる

IPFS で Web サイトを運用するのに便利な Fleek を試してみる

https://fleek.co/

コマンド
mkdir my-first-fleek-website
cd my-first-fleek-website
touch index.html
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello Fleek!</title>
  </head>
  <body>
    <h1>Hello Fleek!</h1>
  </body>
</html>
コマンド
git init
git add .
git commit -m "Initial commit"
gh repo --public create my-first-fleed-website
git remote add origin git@github.com:tatsuyasusukida/my-first-fleed-website
git push origin main

あとは Fleek の Web UI を操作する

Deploy Log
Deploy started at 3:06:31 PM 01/26/2023

3:06:31 PM 01/26/2023: Deploy started
3:06:33 PM 01/26/2023: Docker image: 'node:slim'
3:06:33 PM 01/26/2023: Build command: ''
3:06:33 PM 01/26/2023: Triggering build execution...
3:07:04 PM 01/26/2023: Deployed to IPFS and got the hash:
3:07:04 PM 01/26/2023: QmVM3ovAMkFrG5w1xGVAo8wHRv6zBMfth811xUm5Mysgjg
3:07:04 PM 01/26/2023: Checking content availability on IPFS...
3:07:05 PM 01/26/2023: Updating DNS records...
3:07:06 PM 01/26/2023: DNS was updated. You can visit the new site at:
3:07:06 PM 01/26/2023: https://bold-night-2699.on.fleek.co

デプロイしたサイトには下記のいずれかでアクセスできる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida
  • _dnslink.www.loremipsum.co.jp という名前で TXT レコードを作る
  • レコード内容は "dnslink=/ipns/k51qzi5uqu5di9kl58x19u26pvm1gbhou4a7fhn8d4gr827rqx6221dq5ntcfv" のようにする
  • /ipns/www.loremipsum.co.jp/ でアクセスできるようになる

https://dev.classmethod.jp/articles/ipfs-command-line-quick-start-3-omake/

森 亮介さんの DevelopersIO の記事が豊富で素晴らしい

https://dev.classmethod.jp/author/mori-ryosuke/