EOS 学習メモ:custom dispatcher 編 ②steemCreated with Sketch.

in #eos6 years ago (edited)

dg1uxga7sv.jpg

EOS 学習メモ:custom dispatcher 編 ① の続き。

前回実装した EOSIO_DISPATCH と同じ処理をする dispatcher では、引数として渡された action に対応する action handler を探すために switch 文を利用していたが、例えば、codereceiver が等しいことのチェックをスキップして、外部 contract からの action も受け付けるようにした場合、他に何も修正しなければ、switch 文による条件分岐処理が曖昧さを含んでしまう。すなわち、action が同じであれば、それがどこから飛んできたのかを気にせずに処理することになる。この曖昧さに起因して contract が意図しない振る舞いをした場合、脆弱性に繋がる可能性もある。

ということで、今回は「action がどこから飛んできたのか」を意識してより明示的に処理を切り分けるため、if 文を使って dispatcher を書き直してみた(switch 文でも同様のことを実現できるはずなので、if 文を使うことが本質ではない)。実際のコードは こんな感じ。前回同様、dispatcher だけ抜き出すと以下のようになる。

 extern "C" {
   void apply(uint64_t receiver, uint64_t code, uint64_t action) {
     if (code == receiver && action == name("a").value) {
       execute_action(name(receiver), name(code), &test::a);
     }
     else if (code == receiver && action == name("b").value) {
       execute_action(name(receiver), name(code), &test::b);
     }
     else if (code == receiver && action == name("c").value) {
       execute_action(name(receiver), name(code), &test::c);
     }
     else if (code == name("addressbook").value && action == name("notify").value) {
       execute_action(name(receiver), name(code), &test::notify);
     }
   }
 };



ちょうど、通知について学習した際 に実装した addressbook contract では、各 action の実行時に inline action として実行される notify action が require_recipient() によって action の実行元 account に対して通知を行う仕様になっているので、今回実装した contract の notify action handler が addressbook account からの通知のみをトリガーにして呼び出されるようにしてみる(前回実装した dispatcher の場合、外部から飛んできた action は全てスキップされる)。

毎回 codeaction の双方が何者なのかをチェックしているため、意図した通りの明示的で厳密な条件分岐が行えているが、contract が扱う action が増えるにつれて dispatcher も煩雑になってしまうような書き方なので、保守性はある程度犠牲になってしまっている。

今回はここまで。