結論
データ本体を分散DB(IPFS)に格納して、そのリファレンスをEthereumに格納する。
どこに | なにを | なぜ |
---|---|---|
IPFS | 公開すべきデータ本体 | 低コスト。容量制限なし。可読性が高い。 |
Ethereum | IPFSハッシュ値 | データ本体が改竄されていないことを永続的に保証 |
Overview
Ethereumを公開管理台帳として使おうとしたとき、まず直面するのが、ガスコストが高すぎるという問題。EtherumのOpcodeの中でもストレージ格納の際に実行される"SSTORE"は最も高い。
次に直面するのが容量の問題。Solidityの仕様では容量に上限はないらしい(どんな長い文字列でも格納できる)ものの、Ethereumの仕様ではGas Limitという上限がある。データを格納するとガスコストがかかり、1つのBlockに詰め込めるガス量には上限がある。
つまり、Ethereum単体では公開管理台帳として適さない。そこでIPFSと併用する。世の中の多くのプロジェクトがそうしている。Origin ProtocolやOpenlawもそうしている。IPFSにデータ本体を格納して、IPFSハッシュをEthereumに格納する。
IPFSハッシュのEthereumへの格納の仕方としては"ログ出力"がよい。配列に格納する方法が一般的と思うが、先ほど言及したようにストレージ格納はガスコストが高い。ログ出力ならばその半分程度と安い。もし、削除や何かしらのオペレーションを想定せず、単に格納したいだけならば、ログ出力の方がよい。
実装例
参考のため、具体的な実装例を示す。
1. IPFSハッシュ
IPFSハッシュはByte32型で格納する。理由は、そのままString型で格納するとガスコストが若干高くなるから。Etherumではデータは32byteごとに分割格納される。そして32byte以下だとパックされる。Byte32型が最もお得である。
IPFSハッシュStringのByte32型への変換はBase58デコードで行う。理由は、IPFSハッシュはBase58エンコードされたものだから。
実装はOrigin Protocolのコードを参考にする。
function getBytes32FromIpfsHash(hash) { return `0x${bs58 .decode(hash) .slice(2) .toString('hex')}` }
2. Contranct
ログのガスコストはindexed
された変数の数に依存する。少ない方が安い。
eventSig
イベント名に当たるもの。Ethereumのお作法に従い関数シグネチャと同様に、イベント名をKeccak256 hash
して、その先頭4byteを指定する。
不要なログは記録すべきでないので、modifierにonlyWhitelistAdmin
を指定し、ホワイトリストに登録されたアドレスだけが実行できるようにする。
import 'openzeppelin-solidity/contracts/access/roles/WhitelistAdminRole.sol'; contract IpfsHashRecord is WhitelistAdminRole { event Recorded ( bytes4 indexed eventSig, uint256 indexed createdAt, bytes32 ipfsHash ); function writeHash(bytes4 _eventSig, bytes32 _ipfsHash) public onlyWhitelistAdmin { emit Recorded(_eventSig, uint256(now), _ipfsHash); } }
注意点
IPFSノード運用が必要
IPFSは分散DBであるが、他人がデータを保持するインセンティブがないので、基本的には自分で保持して、外部に公開する必要がある。 IPFSの構築方法については、別記事が参考になる。
個人情報秘匿が必要
BlockchainとIPFSは外部に公開されるので、多くの場合は個人情報を秘匿する必要がある。秘匿手法は無数に考えられるるが、フィナンシェで採用した方法はこちら。
用途
- デジタル所有権の記録と証明
デジタル作品のハッシュ値と所有者の情報をBlockchainに記録する。 作品そのものをBlockchain上に格納するとガスコストが高くなるのでハッシュ値のみ。ハッシュ化アルゴリズムは何でもよいが、IPFSを使うのが楽。Blockchainは改竄が困難なので、所有権を立証できる。
- プラットフォーム潔白性の検証と証明
例えば決済プラットフォームの運営主体が、取引に不正がないことを証明したいとする。Dappsのようにビジネスロジックをオンチェーンで実行すれば、それで済む話だが、多くの場合はそうではないはずだ。そこで、取引の結果のみBlockchainに格納する。一度格納すると後から改竄は困難。全ての取引結果から現在の状態を復元できれば、取引に不正がないことを証明できる。ちなみに、フィナンシェはこの用途で使っている。
- ERC20のようなプロトコル
例えばeventSig
をこのように、トークンの名前と関数の結合と定義する。
eventSig => First 4 bytes of Keccak256(“token_name:transferFrom”)
そして、IPFSにその他の情報(送信者、受信者、額)を格納する。
{ from: 0x825bBB7fdD9292ba18913c1E784D839DbEF82BbB, to: 0x49Cb60853D1a527995F6CB784e9641bb408dBb51, value: 10000000 }