紹介#
インタープラネタリーファイルシステム(IPFS)は、分散ストレージ、共有、永続化を実現するためのネットワーク転送プロトコルです。これは、コンテンツアドレス可能なピアツーピアのハイパーメディア配信プロトコルです。IPFS ネットワーク内のノードは、分散ファイルシステムを構成します。
主な特徴は次のとおりです。
- 弾力性のあるネットワークのサポート:従来のインターネットでは、ファイルは中央集権型のサーバーに保存されます。ファイルサーバーがダウンした場合、ファイルにアクセスできなくなります。しかし、
IPFS
では、他のノードからファイルを取得することもできます。 - コンテンツの検閲が困難:
IPFS
上のファイルはさまざまな場所から取得できるため、ブロックするのがより困難です。 - より高速なファイル取得速度:近くのノードからファイルを取得できるため、より遠い場所よりもアクセス速度が大幅に向上します。(CDN と同様)
現在の Web は所有権とアクセス権を基にして構築されています。つまり、ファイルを所有者から取得するには、まずアクセス権を取得する必要があります。しかし、IPFS
は所有と参加の理念に基づいています。つまり、人々はお互いのファイルを所有し、提供することに参加しています。
IPFS
は、人々が積極的に参加する場合にのみ効果的に機能します。たとえば、IPFS
を使用してファイルを共有するためにコンピュータを使用している場合、後でコンピュータをシャットダウンすると、他の人はあなたからファイルを取得できなくなります。ただし、IPFS
を実行している他のコンピュータにファイルのコピーが保存されている場合、これらのファイルは共有できます。
動作原理#
IPFS は、次の 3 つの基本原則に従います。
-
コンテンツアドレスによる一意の識別
通常、ファイルのパスは場所に基づいています。ローカルファイル
/Users/..../code.js
やアクセス可能なネットワーク上のファイルhttp://www.google.com/index.html
などです。しかし、
IPFS
のファイルパスはアドレスではなく、ファイルの内容に基づいています。IPFS
はファイルの内容に基づいて暗号化されたハッシュ値を生成し、それをパスの一部として使用します。以下のアドレスのipfs/
の後に続く内容です。/ipfs/QmcuLr8xuHm6ViSYuppjDxCXE8vDuUBKmdAwcrTJRRnEUY
IPFS
は、ファイルの場所ではなく、その内容に基づいてファイルを特定するため、コンテンツアドレスを使用します。IPFS
プロトコルを使用するファイルごとに一意のコンテンツ識別子(CID)があります。このハッシュ値はファイルにとって一意です。 -
有向非巡回グラフ(DAG)によるコンテンツリンク
IPFS
は、他の多くの分散システムと同様に、有向非巡回グラフ(DAG)と呼ばれるデータ構造を使用します。具体的には、メルクル有向非巡回グラフ(Merkle DAG)を使用します。ファイルの
Merkle DAG
を構築するために、通常、IPFS
はまずファイルをチャンクに分割します(チャンク化は、異なる部分が異なるソースから来て、高速に検証できることを意味します)。チャンクの内容はハッシュ関数によってハッシュ値に変換され、CID
としてMerkle DAG
のノードとして使用されます。これらのノードは再びハッシュ関数を通過し、ファイルのCID
が得られます。同様に、フォルダ内のファイルも、フォルダ内のファイルの内容に基づいてハッシュ関数を通過し、フォルダの
CID
が得られます。似たような 2 つのファイルがある場合、ファイルのチャンク化後に生成される
CID
が同じであれば、同じデータサブセットを参照でき、重複を効果的に削減できます。たとえば、ファイルを更新する場合、更新されたファイルと更新されていないファイルの最初のチャンクの
CID
が同じであれば、同じチャンクを参照できます。再作成する必要はありません。したがって、
IPFS
はコンテンツにCID
を割り当て、これらのコンテンツをMerkle DAG
にリンクします。 -
分散ハッシュテーブル(DHT)によるコンテンツの発見
DHT
の主なアイデアは、ネットワーク全体で巨大なファイルインデックスハッシュテーブルを維持することです。このハッシュテーブルのエントリは<Key,Value>
の形式です。ここで、Key
は通常、ファイルのハッシュアルゴリズムによるハッシュ値(またはファイル名またはファイルの内容の説明)であり、Value
はファイルを保存する IP アドレスです。クエリを実行する場合、Key
のみを提供すれば、テーブルから対応するノードのアドレスをクエリできます。このハッシュテーブルは非常に大きいため、それを小さなブロックに分割し、特定のアルゴリズムとルールに従ってネットワーク全体のノードに分散させます。
各ノードは小さなブロックのハッシュテーブルのみを維持する必要がありますが、各ブロックのハッシュテーブルは複数のノードによって維持されます(これにより、ノードが予期せずにダウンしてもDHT
が利用可能になります)。ノードがクエリリクエストを受け取ると、** 自分のバケット(各ノードが維持する
DHT
のサブセットを「バケット」と呼ぶ)** で見つかる場合は応答し、そうでない場合は最も近いノードに連絡します。このプロセスは、ターゲットノードが見つかるまで続きます。
これらの 3 つの原則は互いに依存し、IPFS のエコシステムを実現します。
使用方法#
コマンドラインでの使用#
js-ipfsをコマンドラインでインストールします。
$ npm install -g ipfs
またはクライアントをインストールすることもできます https://ipfs.tech/#install
ipfs
リポジトリを初期化します。
$ jsipfs init
initializing ipfs node at .jsipfs
ローカルのipfs
ネットワークインスタンスを起動します。
$ jsipfs daemon
Initializing IPFS daemon...
HTTP API listening on /ip4/127.0.0.1/tcp/5002/http
gRPC listening on /ip4/127.0.0.1/tcp/5003/ws
Gateway (read only) listening on /ip4/127.0.0.1/tcp/9090/http
Web UI available at http://127.0.0.1:5002/webui
Daemon is ready
ファイルを追加します。
$ jsipfs add util.ts
added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH util.ts
ファイルの内容にアクセスします。
$ jsipfs cat QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH
API の使用#
まず、ipfs
ノードとしてアクセス可能なパブリックネットワークサーバーが必要です。自分のパブリックサーバーまたはinfuraサービスを選択できます。ここでは、infura
を例に説明します。また、5G の無料スペースも利用できます。infura
でipfs
プロジェクトを作成すると、projectId
とprojectSecret
が生成されます。
インストール#
プロジェクトにipfs-http-client
をインストールします。
$ yarn add ipfs-http-client
初期化#
import { create, urlSource, CID } from 'ipfs-http-client'
import fs from 'node:fs'
const projectId = 'xxxxxx'
const projectSecret = 'xxxxxx'
const auth = 'Basic ' + Buffer.from(projectId + ':' + projectSecret).toString('base64')
const ipfs = create({
host: 'ipfs.infura.io',
port: 5001,
protocol: 'https',
headers: {
authorization: auth
}
})
リソースのアップロード#
const upload = async () => {
// ローカルファイル、ネットワークリソース、テキストをアップロードする
// 1. ローカルリソース
const file = fs.readFileSync('./test.sol', 'utf-8')
// 2. ネットワークリソース
//const file = urlSource('https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png')
// 3. テキスト
// const file = 'hello world'
const result = await ipfs.add(file)
console.log(result)
}
upload()
アップロードが成功すると、以下のような形式のコンテンツが返されます。
{
path: 'QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q',
cid: CID(QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q),
size: 593
}
ブラウザのアドレス https://ipfs.infura.io/ipfs/${path}
を使用して、コンテンツにアクセスできます。
リソースの読み取り#
const cat = async () => {
const decoder = new TextDecoder();
let content = '';
for await (const chunk of ipfs.cat('QmNvHxnJQ6Ho9LWw1FwCn3nqcJXSeM76cmmd6JvoLEzW8Q')) {
content += decoder.decode(chunk);
}
console.log(content)
}