Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Closures #783

Open
Stebalien opened this issue Oct 21, 2021 · 0 comments
Open

Feature Request: Closures #783

Stebalien opened this issue Oct 21, 2021 · 0 comments

Comments

@Stebalien
Copy link
Member

Use-cases:

  1. Async callbacks (and, in general, asynchronous messaging).
  2. Programmable conditions. E.g., "this voucher is only valid when....".
  3. Capabilities. A closure can be used to grant transferable access to some privileged endpoint by closing over the current "authority" in addition to some state.

Actor to actor

On-chain, this is relatively easy. The naive implementation would be to keep a table mapping closure "handles" (numbers) to saved state, the closure's function, and the actor that's actually allowed to call the closure.

Let's assume that actor A is sending a closure to actor B:

  1. To create the closure, actor A would add the closure information (along with actor B's address) to this closure table, resulting in a closure handle H.
  2. Actor A would then send H to actor B.
  3. To call the closure, actor B send a message back to actor A with the closure handle H and some parameters.
  4. Actor A would lookup and call closure H, verifying that actor B is "authorized" to invoke the closure.
  5. If the closure is "run once", actor A would remove it from the table.

But what if actor B needs to send a message to some actor C, and wants actor C to invoke actor A's closure? In this case, we have two mostly equivalent options:

  1. Provide some way for actor A to delegate/forward the closure. In this case, actor B would need to tell actor A to authorize actor C to call H.
    1. Pro: Actor C can now directly call the closure on actor A.
    2. Con: Actor B needs to call actor A when forwarding the closure.
  2. Create a new closure.
    1. Pro: Actor B can forward the closure without involving actor A
    2. Pro: Actor B can "wrap" the closure in it's own logic.
    3. Con: When C invokes the closure, it'll have to call B which will, in turn, call A.
    4. Con: Actor B needs to "remember" the closure it gave to C.

There are still two open questions here:

  1. What about pure functions? Calling back into the original actor just to execute a pure function is expensive. Furthermore, tracking these pure functions could limit their usefulness. It would be nice to be able to dynamically load up some WASM module and invoke a function on it.
  2. Garbage collection is tricky. There's no good way for actor A to know that actor B has "dropped" the closure.

User to Actor

It would be really useful to specify complex conditions (ideally as pure functions) in messages sent from the user to the chain. This could be done in multiple steps (load the condition onto the chain, then send a message that refers to that condition) but it would be convenient, and likely cheaper, to be able to include a small lambda inline in messages.

@raulk raulk added the MIGRATED label Aug 18, 2022
@raulk raulk transferred this issue from filecoin-project/fvm-specs Aug 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants