紹介#
インタープラネタリーファイルシステム(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)を使用しています。
ファイルのメルクル 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)
}