Returning a Capability via SessionContext.fulfillRequest using sandstorm-rust

35 views
Skip to first unread message

Troy Farrell

unread,
Aug 26, 2021, 9:27:16 AM8/26/21
to Sandstorm Development

Hi Sandstormers,

I'm trying to understand how to connect grains with capabilities.  I've made more progress than I had expected, but I'm stuck trying to set a capability on the fulfillRequest call.  Here's where I am:


The fourth paragraph says, "Your powerbox request UI should implement a picker or configuration dialog which allows the user to specify exactly what they want your app to return. Once the user has made their choice, your app calls SessionContext.fulfillRequest() on the user's session object, passing it a capability that fulfills the request."

I'm using Rust and sandstorm-rust, which I don't know well.  Here's what I have:

let client: hello_capnp::hello::Client = capnp_rpc::new_client(HelloImpl);
let mut req = self.session_context.fulfill_request_request();
req.get().set_cap(client);

This follows the pattern that I see in sandstorm-http-bridge.c++:


The Rust compiler is not OK with my call to set_cap().  It seems that set_cap() does not exist:

error[E0599]: no method named `set_cap` found for struct `sandstorm::grain_capnp::session_context::fulfill_request_params::Builder` in the current scope
  --> src/server/bin/hello_request_view.rs:52:19
   |
52 |         req.get().set_cap(client);
   |                   ^^^^^^^ help: there is an associated function with a similar name: `get_cap`


With this in mind, I have a few questions:

1. Is my Client the right thing to pass as a Capability?  (I can't find a definition for :Capability in grain.capnp.)
2. How can I pass the Client if set_cap() does not exist?

Thanks for your help!
Troy

Troy Farrell

unread,
Aug 27, 2021, 12:23:54 AM8/27/21
to Sandstorm Development
I found "capability" in schema.capnp.  I'm not sure how this maps to :Capability in grain.capnp, since the case does not match.

Having spent several more hours trying to understand this, I believe that capnproto-rust does not have special :Capability support, separate from its generic handling of anyPointer.  I believe that this makes it impossible to call SessionContext.fulfillRequest() from sandstorm-rust.  I would be grateful if anyone can show me otherwise.

I expect that my quest will continue on the capnproto mailing list where I'm going to explore the difficulty of adding the necessary support to capnproto-rust.

Thanks,
Troy

D Mallows

unread,
Aug 27, 2021, 6:02:22 AM8/27/21
to Sandstorm Development
Hi Troy,

Long-term lurker here. I told myself I would dive in and offer some help.

I found "capability" in schema.capnp.  I'm not sure how this maps to :Capability in grain.capnp, since the case does not match.

I always understood that Capability is like AnyPointer but restricted to capabilities.
 
Having spent several more hours trying to understand this, I believe that capnproto-rust does not have special :Capability support, separate from its generic handling of anyPointer.  I believe that this makes it impossible to call SessionContext.fulfillRequest() from sandstorm-rust.  I would be grateful if anyone can show me otherwise.

I found that the Collections app (https://github.com/sandstorm-io/collections-app/) to be very useful for both using the sandstorm APIs and capnproto-rust.

I believe you need to get the field, then set_as_capability. If you take a look in https://github.com/sandstorm-io/collections-app/blob/master/src/server.rs, you’ll see set_as_capability is used a few times. On line 819:

req.get().get_cap().set_as_capability(sealed_ui_view.client.hook);

Without digging into the internals, I think in your case that would look something like:

req.get().get_cap().set_as_capability(client.client.hook);

Not 100% sure about the implications of the .client.hook stuff, but that’s the way it’s done in the collections app.

I find for me this stuff does take a lot of time to understand, and have had similar battles using both capnproto-rust and pycapnp. I wish you luck with whatever you are doing. It can be a battle at times, and sometimes you will find under-documented or not-yet-implemented bits of API; to me, that is the price to pay for interesting tech.

Hope this helps,
Dave

Troy Farrell

unread,
Aug 27, 2021, 9:42:44 AM8/27/21
to Sandstorm Development
Thanks Dave!

Dave wrote:

I always understood that Capability is like AnyPointer but restricted to capabilities.

That matches my understanding now.  I found that the documentation talks about doing things with capabilities without giving a concrete example of what that looks like.  I've had a vague understanding that a capability is an object that carries abilities, but I need to see code that created and used a capability.

I found that the Collections app (https://github.com/sandstorm-io/collections-app/) to be very useful for both using the sandstorm APIs and capnproto-rust.

I actually looked at the collections app and missed the lines that you pointed out.  I think that I got tunnel vision and was looking for fulfillRequest instead of looking for other places where capabilities are used.

I believe you need to get the field, then set_as_capability. If you take a look in https://github.com/sandstorm-io/collections-app/blob/master/src/server.rs, you’ll see set_as_capability is used a few times. On line 819:

req.get().get_cap().set_as_capability(sealed_ui_view.client.hook);

Without digging into the internals, I think in your case that would look something like:

req.get().get_cap().set_as_capability(client.client.hook);

Not 100% sure about the implications of the .client.hook stuff, but that’s the way it’s done in the collections app.

You're exactly right.  I tried that and it works!  Brilliant!
 
I find for me this stuff does take a lot of time to understand, and have had similar battles using both capnproto-rust and pycapnp. I wish you luck with whatever you are doing. It can be a battle at times, and sometimes you will find under-documented or not-yet-implemented bits of API; to me, that is the price to pay for interesting tech.
 
Yes, it can be frustrating.  I don't think that I would have gotten this far if I weren't so stubborn.  Thanks for taking the time to help!

Troy
Reply all
Reply to author
Forward
0 new messages