moon

moon

Build for builders on blockchain
github
twitter

IPFSの紹介

公式

紹介#

インタープラネタリーファイルシステム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 の無料スペースも利用できます。infuraipfsプロジェクトを作成すると、projectIdprojectSecretが生成されます。

インストール#

プロジェクトに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)
}
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。