EOS 学習メモ:custom dispatcher 編 ① の続き。
前回実装した EOSIO_DISPATCH
と同じ処理をする dispatcher では、引数として渡された action
に対応する action handler を探すために switch
文を利用していたが、例えば、code
と receiver
が等しいことのチェックをスキップして、外部 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 は全てスキップされる)。
毎回 code
と action
の双方が何者なのかをチェックしているため、意図した通りの明示的で厳密な条件分岐が行えているが、contract が扱う action が増えるにつれて dispatcher も煩雑になってしまうような書き方なので、保守性はある程度犠牲になってしまっている。
今回はここまで。