IOSTでほとんどRAMを使わずにデータを保存する方法


はじめに

ブロックチェーンのユースケースの一つとして「何かの履歴」を証明として残すということがあると思います.
Ethereumとかを使うと,RAMエコシステムがないので,ストレージ利用は高価.データを消してもETHは戻らない.
でもIOSTの場合はRAMエコシステムがあるおかげで,使い終わったストレージ領域は削除するとRAMトークンが返却されてストレージの再利用ができる.
なので,IOSTの場合は使わなくなったストレージは積極的に削除すべきということだ.
ストレージデータのいいところは「書き換えられる」ということだ.でも履歴データって書き換えますか??ないですよね.
じゃあ履歴データはずっとRAMに残しておく必要は無いですよね.
とりあえずスマートコントラクトのコードを見ていきましょう.

悪い例

ずっとRAMに履歴を記録していくスタイル

class BadHistory {
  init() {}
  add(attr, action) {
    const history = JSON.parse(storage.mapGet(tx.publisher, attr)) || [];
    history.push(action);
    storage.mapPut(tx.publisher, attr, JSON.stringify(history));
  }
  destroy(attr) {
    storage.mapDel(tx.publisher, attr);
  }
}

これだと,履歴データが増えるにつれてRAMの使用料がかさんでいきます.(この例だとGASもかかってきますね.)

提案する方法

class NiceHistory {
  init() {}
  add(attr, action) {
    const prev = storage.mapGet(tx.publisher, attr);
    if (tx.hash === prev)
      throw new Error('duplicated tx hash');
    blockchain.receipt(JSON.stringify({ action, prev }));
    storage.mapPut(tx.publisher, attr, tx.hash);
  }
  destroy(attr) {
    storage.mapDel(tx.publisher, attr);
  }
}

これだと,履歴が増えてもRAMの利用は一定値のままになる.
アイデアは,ブロックチェーンの上にチェーン作ってしまおうって感じ.
最新の履歴のTxHashだけRAMに記録しておいて,更新があるたびにreceiptに流す.
参照方法は,最初RAMにアクセスして最新Txを得てgetTxReceiptでデータを取得,そのreceiptにさらに一つ前のTxHashが乗っているので同様に参照...を続けていく.TxHashがnullになれば終了だ.
この方法のデメリットは,全履歴へのアクセスまでに時間がかかるという点だ.