ref-fvm
ref-fvm copied to clipboard
Syscall Access Control
For Account Abstraction we will be needing to constrain the available syscalls for both validate contexts and invoke on abstract accounts. Work done here will also apply towards https://github.com/filecoin-project/ref-fvm/pull/654 though it is not listed in the table.
β available
π« forbidden
β not linked
β³οΈ see notes
βTODO
| Module | Syscalls | Validate | Invoke (account actor) | Invoke (normal) | Builtin | Notes | Abstract Account Notes | Β |
|---|---|---|---|---|---|---|---|---|
| vm | abort | β | β | β | β | Β | Β | Β |
| Β | context | π« | β | β | β | probably rename to invoke_context | Β | Β |
| Β | validate_context | β β | β | β | β | Β | TODO | Β |
| network | base_fee | π« | β | β | β | Β | Β | Β |
| Β | total_fil_circ_supply | π« | β β | β β | β | TODO maybe constrain to only builtin actors | Β | Β |
| ipld | block_open | β β³οΈ | β | β | β | Β | state mutations is not saved on chain | Β |
| Β | block_create | β β³οΈ | β | β | β | Β | state mutations is not saved on chain | Β |
| Β | block_read | β | β | β | β | Β | Β | Β |
| Β | block_stat | β | β | β | β | Β | Β | Β |
| Β | block_link | β β³οΈ | β | β | β | Β | state mutations is not saved on chain | Β |
| self | root | β | β | β | β | Β | Β | Β |
| Β | set_root | π« | π« | β | π«β | Β | Β | Β |
| Β | current_balance | π« | β | β | β | Β | Β | Β |
| Β | self_destruct | π« | π«ββ³οΈ | ββ β³οΈ | π« | only if self == origin? | Spec before this is final | Β |
| actor | resolve_address | π« | β | β | β | Β | Β | Β |
| Β | get_actor_code_cid | π« | β | β | β | Β | Β | Β |
| Β | new_actor_address | π« | β β | β ββ³οΈ | β | TODO merge with create_actor | Β | Β |
| Β | create_actor | π« | β β | β ββ³οΈ | β | only init actor (!current implementation doesnβt check!) | Β | Β |
| Β | get_builtin_actor_type | π« | β | β | β | Β | Β | Β |
| Β | get_code_cid_for_type | π« | β | β | β | Β | Β | Β |
| Β | install_actor | π« | β ββ³οΈ | β ββ³οΈ | β | only for m2 native, TODO be done through init actor in the future | changes done in invoke cant effect validate | Β |
| crypto | hash | β | β | β | β | Β | Β | Β |
| Β | recover_secp_public_key | β | β | β | β | Β | Β | Β |
| Β | compute_unsealed_sector_cid | π« | β β | β β | β | TODO maybe just defer to a Builtin Actor | Β | Β |
| Β | verify_seal | π« | β β | β β | β | TODO maybe constrain to Builtin actor type | Β | Β |
| Β | verify_post | π« | β β | β β | β | TODO maybe constrain to Builtin actor type | Β | Β |
| Β | verify_consensus_fault | π« | β β | β β | β | TODO maybe constrain to Builtin actor type | Β | Β |
| Β | verify_aggregate_seals | π« | β β | β β | β | TODO maybe constrain to Builtin actor type | Β | Β |
| Β | verify_replica_update | π« | β β | β β | β | TODO maybe constrain to Builtin actor type | Β | Β |
| Β | batch_verify_seals | π« | β β | β β | β | only power actor (!current implementation doesnβt check!) | Β | Β |
| rand | get_chain_randomness | π« | β | β | β | Β | Β | Β |
| Β | get_beacon_randomness | π« | β | β | β | Β | Β | Β |
| gas | charge | π« | β β | β β | β | to be unlinked for non-system actorsΒ | Β | Β |
| send | send | π« | π«ββ³οΈ | β | β | Β | Spec before this is final | Β |
| debug | enabled | β | β | β | β | Β | Β | Β |
| Β | log | β β³οΈ | β β³οΈ | β β³οΈ | β β³οΈ | error if !enabled | Β | Β |
| Β | store_artifact | β β³οΈ | β β³οΈ | β β³οΈ | β β³οΈ | error if !enabled | Β | Β |
Account Abstraction adds validate_context and origin syscalls.
upgrade should be ran in a constrained runtime as well, but that is a later TODO.
Implementation
Goals
- Pave the way for future differently constrained runtimes.
- Keep actor types and syscalls composable where expected.
Appoaches
- Runtime value inside
Kernelthat is checked on syscalls that are constrained at any point. This ends up being most syscalls. - Lean into rust traits to constrain syscall binding to certain bounds, with runtime implementation checks done inside kernel.
- Syscall permission table per-mode, listing what syscalls are available with a closure for runtime checks.
cc @Stebalien
I see three major types of binding:
- Always forbidden
- Always allowed
- Sometimes allowed (runtime check)
Always allowed can be done with a runtime check and be considered part of Somtimes allowed, though it probably get messy quick.
Unbound is another one potentially, but it could implemented as Always forbidden. This would mean all actors would need to import syscalls like validate_context and become_actor.
General notes:
- Invoke shouldn't differ between normal actors and abstract accounts except that abstract accounts can't set their own state or delete themselves.
- The "builtin only" methods should only be linked to builtin actors (so they don't appear as part of the public API). They're not dangerous (generally), just unstable.
Unbound is another one potentially, but it could implemented as Always forbidden.
(see my comment about builtin actors).
This would mean all actors would need to import syscalls like validate_context and become_actor.
Actors can choose to not import a defined syscall.
A note on get_code_cid_for_type and get_builtin_actor_type reasons' for being disallowed in validate contexts:
Both functions breaks the (currently thought) contract of validate being solely a pure function of its own state and the message it validates. By allowing either of these, actors can write code that can test for what version of the network it is currently running on, and as such breaks that contract.
on the same hand, gas_available can give hints as well by doing test operations that it knows are more expensive/cheaper on different versions of the runtime and gathering information that way, though it is a bit less accurate and easy.
We're no longer implementing the validate entry point in this M2.1, so we can punt this to M2.2.