You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Technically the kernel allows a decider to got from the exporting vat, to the kernel, to another vat, back to the kernel, then to another vat, etc. The decider can change one of 2 ways:
An existing promise is used as the result of a send
A promise is forwarded to another promise
In practice neither can currently happen:
liveslots and comms vat always create a new promise
Forwarding is not implemented
Description of the Design
If we assume that the decider will never change more than vat exporting new promise -> kernel -> receiver of message tied to result promise, then messages sent to the promise can only ever be placed on the promise queue (while the kernel is decider, or if the decider vat doesn't support pipelining), or the decider pipelining vat (aka comms only for now), and will only ever move from the first to the second.
This ties in with #4542 so that messages can be enqueued to the correct queue right away.
In the future, when forwarding is supported, simply placing a forwarding on the vat outbound queue will need to synchronously pluck messages sent to the promise that were sitting on the pipelining vat's inbound queue, and move them back to the kernel's promise's queue until the forwarding is later processed from the outbound queue.
Security Considerations
Audit kernel and liveslot code which deals with decider changes, and add assertions as necessary.
Test Plan
Update existing unit tests and add new negative tests.
The text was updated successfully, but these errors were encountered:
After looking deeper into this, @warner and I realized that comms may in fact re-use an imported promise as the result of another send:
B exports a promise to A (e.g nested inside resolution data, or as arguments)
B learns that the previously exported promise is resolved, and the resolution is an object in A
B notifies A about the resolution (A was automatically subscribed), and begins retiring the promise
B receives a message from A targeted at the promise, with a result promise allocated by A. The message was already in flight / A hadn't heard about the resolution yet
B turns around and send the message back to the resolved target in A, and re-uses the result promise A had allocated
A receives the resolve from B
A receives the send from B for its own object, but its using a result promise that A had initially exported to B
Furthermore, there are legitimate cases where the kernel will need to pluck or gate messages pending in a pipelining vat's inbound queue to prevent delivering them:
Kernel queues message send for an object onto pipelining vat, marking the result promise as decided by the vat
kernel queues message send for the result promise onto the pipelining vat
vat processes the object send, and messages the kernel with a resolve for the result promise using an object owned by another vat of the kernel (allowing it to forget about the promise)
kernel can no longer deliver the pending messages for the promise to the pipelining vat, and must redirect them appropriately
This summary is that:
Comms must be able to reuse an existing promise when processing a remote message, regardless of whether it was imported or exported by the remote
A pipelining vat like comms must be allowed to use an imported promise it's the decider of as the result of a message send. However liveslots will never produce such a case: it doesn't support pipelining and cannot realize ahead of time that the result of a send done by the contract will be later used as the return value of the current delivery (this would require some static analysis of the code / compilation to non JavaScript)
The kernel must handle pending messages pipelined to a promise when that promise is resolved
What is the Problem Being Solved?
Technically the kernel allows a decider to got from the exporting vat, to the kernel, to another vat, back to the kernel, then to another vat, etc. The decider can change one of 2 ways:
In practice neither can currently happen:
Description of the Design
If we assume that the decider will never change more than vat exporting new promise -> kernel -> receiver of message tied to result promise, then messages sent to the promise can only ever be placed on the promise queue (while the kernel is decider, or if the decider vat doesn't support pipelining), or the decider pipelining vat (aka comms only for now), and will only ever move from the first to the second.
This ties in with #4542 so that messages can be enqueued to the correct queue right away.
In the future, when forwarding is supported, simply placing a forwarding on the vat outbound queue will need to synchronously pluck messages sent to the promise that were sitting on the pipelining vat's inbound queue, and move them back to the kernel's promise's queue until the forwarding is later processed from the outbound queue.
Security Considerations
Audit kernel and liveslot code which deals with decider changes, and add assertions as necessary.
Test Plan
Update existing unit tests and add new negative tests.
The text was updated successfully, but these errors were encountered: