Internet Computer では, キャニスタが HTTP インタフェイス経由で入ってくるメッセージを選択的に監査して, 受諾/拒絶 できます.

On the Internet Computer, a canister can selectively inspect and accept or decline ingress messages submitted through the HTTP interface:

キャニスタは, 実行前に入ってくるメッセージを監査することができます. IC がユーザから更新呼び出しを受け取ると, IC はキャニスタのメソッド canister_inspect_message を使って, メッセージを受け取るかどうかを決めます. キャニスタが空の (すなわち Wasm モジュールを持っていない) ときには, 入って来たメッセージは拒絶されます. キャニスタが空でなく, canister_inspect_message を実装していなければ, 入って来たメッセージは受け入れられます.

キャニスタは canister_inspect_message 内で ic0.accept_message : () → () を起動することでメッセージを受け入れることができます. 二度起動されるとこの関数はトラップを起こします. キャニスタが canister_inspect_message でトラップしたり, ic0.accept_message を呼び出さなければ, アクセスは拒否されます.

canister_inspect_message は HTTP の問い合わせ呼び出し, キャニスタ間呼び出し, 管理キャニスタに対する呼び出しに対しては起動され ません.

IC Interface Specification

A canister can inspect ingress messages before executing them. When the IC receives an update call from a user, the IC will use the canister method canister_inspect_message to determine whether the message shall be accepted. If the canister is empty (i.e. does not have a Wasm module), then the ingress message will be rejected. If the canister is not empty and does not implement canister_inspect_message, then the ingress message will be accepted.

In canister_inspect_message, the canister can accept the message by invoking ic0.accept_message : () → (). This function traps if invoked twice. If the canister traps in canister_inspect_message or does not call ic0.accept_message, then the access is denied.

The canister_inspect_message is not invoked for HTTP query calls, inter-canister calls or calls to the management canister.

IC Interface Specification

メッセージ監査は, 望まざる無料呼び出しによってキャニスタのサイクルを枯渇させるようなサービス攻撃を軽減します.

Message inspection mitigates some denial of service attacks, designed to drain canisters of cycles by placing unsolicited free calls.

:::note

メソッド監査は「誰々 さんからコレクトコールです. お出になりますか」という, 昔風の交換手が出てくる電話のコレクト・コールの前置きのようなものだと考えてください.

You can think of method inspection as providing the "Collect call from name. Do you accept charges?" prologue of an old-fashioned, operator-assisted, collect phone call.

:::

Motoko では, アクタは inspect という特別な system 関数を宣言することで, 入ってくるメッセージを監査して, そのメッセージを受けれるかどうかを選択することができます. 与えられたメッセージ属性のレコードに対して, この関数は Booltruefalse を返すことで, そのメッセージを許諾するか, 拒絶するかを示します. この関数は, 内向きのメッセージ毎に (システムによって) 起動されます. 問い合わせと同じように, その起動による副作用はすべて棄てられ, 一時的なものになります. 何らかの失敗によってトラップした呼び出しは, false を返すのと同じ結果 (メッセージ拒絶) になります.

In Motoko, actors can elect to inspect and accept or decline ingress messages by declaring a particular system function called inspect. Given a record of message attributes, this function produces a Bool that indicates whether to accept or decline the message by returning true or false. The function is invoked (by the system) on each ingress message. Similar to a query, any side-effects of an invocation are discarded and transient. A call that traps due to some fault has the same result as returning false (message declination).

他のシステム関数とは異なり, この関数は決まった引数型を持ちますが, inspect の引数の型はそのアクタを囲むインタフェイスによって変わってきます.

Unlike other system functions, that have a fixed argument type, the argument type of inspect depends on the interface of the enclosing actor. In particular, the formal argument of inspect is a record of fields of the following types:

#<id> でタグ付けされたヴァリアントを用いて, 復号関数は型 T を返すことができますが, この型は共有関数 <id> の引数の型 (これも T) に応じて変わります.

Using a variant, tagged with #<id>, allows the return type, T, of the decoding function to vary with the argument type (also T) of the shared function <id>.

このヴァリアントの引数は関数なので, (それが適切であれば) メッセージ復号の手間を避けることもできます.

The variant’s argument is a function so that one can avoid the expense of message decoding (when appropriate).

副型付けを活用し, 仮引数で必要ではないレコードを省いたり, 特定の共有関数の引数を選んで無視したりして, 関数を監査せずにその関数の名前を処理しても構いません.

Exploiting subtyping, the formal argument can omit record fields it does not require, or selectively ignore the arguments of particular shared functions, for example, in order to simply dispatch on the name of a function without inspecting its actual argument.

:::note

紛らわしいですが, 共有問い合わせ 関数でも, 認証された応答を得るために (敢えて) 通常の HTTP 経由で呼び出しすることもできます. ヴァリアント型に 共有問い合わせ 間も含まれているのはそのためです.

Confusingly, a shared query function can be called using a regular HTTP call to obtain a certified response: this is why the variant type also includes shared query functions.

:::

:::danger

inspect システム・フィールドを宣言し損なっていると, すべての内向きのメッセージを受け取ることになってしまいます.

An actor that fails to declare system field inspect will simply accept all ingress messages.

:::

:::danger

システム関数 inspect を最終的なアクセス制御に用いては いけません. なぜならば inspect は完全な同意ではなく一つのレプリカで実行され, その結果は悪意のある境界ノードによってなりすまされる可能性があるからです. 信頼のおけるアクセス制御の検査は inspect によって保護された 共有 関数内部でのみ実行可能です.

System function inspect should not be used for definitive access control. This is because inspect is executed by a single replica, without full consensus, and its result could be spoofed by a malicious boundary node. Reliable access control checks can only be performed within the shared functions guarded by inspect.