On 6 September 2017 at 18:16, Kenton Varda <
ken...@cloudflare.com> wrote:
> Hi Thomas,
>
> Sorry I missed this earlier!
>
> So, "level 2" of the RPC protocol / SturdyRefs turn out to be something that
> does not make sense to specify as part of the Cap'n Proto implementation
> itself. Probably level 2 should be ripped out of the spec entirely. This is
> what we learned as we build Sandstorm: SturdyRefs and how to restore them
> turned out to be intrinsically tied to the Sandstorm environment, and
> attempts to define an "abstract" SturdyRef format not dependent on Sandstorm
> did not seem to fit what Sandstorm needed.
>
> To understand this, consider a few different cases:
> - A Sandstorm grain (app instance).
> - A node in the Blackrock (clustered Sandstorm) infrastructure.
> - An application on the general internet that has nothing to do with
> Sandstorm.
>
> Now try to answer the question: What does a SturdyRef express, and how does
> one restore it?
At the application level:
It represents the ability to get a live capability reference to a
service. You restore it by calling its "connect" method (which is
possibly the only method it has).
At the vat/network level: whatever the network defines it as.
(using "SturdyRef" to mean both of these things is perhaps confusing though)
> The answer is totally different depending on the context:
>
> - For a Sandstorm grain, a SturdyRef can be an opaque byte string, which
> refers to an object in another grain. The client grain passes the SturdyRef
> to the Sandstorm API to restore it. The Sandstorm infrastructure then looks
> up the token in its database, verifies that the token belongs to the
> requesting grain, finds out to what grain the token points, starts up that
> grain, asks that grain for a live ref of the desired capability, and then
> returns that to the requesting grain.
>
> - For a Blackrock node, a SturdyRef typically refers to another component of
> the Blackrock infrastructure: maybe an object in Blackrock storage (a graph
> store of Cap'n Proto objects), or a running container on one of the worker
> nodes. Or, it could also refer to something hosted in a grain, or a totally
> external capability. See the definition here:
>
https://github.com/sandstorm-io/blackrock/blob/master/src/blackrock/cluster-rpc.capnp#L67
That's a useful link, thanks!
> If the sender's public key
> is less than the receiver's, this number must be even, otherwise it must be odd, so that
> connection IDs in opposite directions between the same vats never collide. Any existing
> connections with lower connection IDs must be invalidated when a new connection starts.
That's useful to have specified. For my implementation, the rule I
used was "the connection to keep is the one initiated by the peer with
the highest vat ID." But your scheme looks better, as it copes with
one vat losing a connection and retrying while the other thinks the
old connection is still OK. Can I use this header format with e.g. the
Python client? My current code does have the advantage of being just
plain TLS with client and server certificates.
> Notice how the namespace of SturdyRefs as seen by the infrastructure itself
> is completely different from the namespace of SturdyRefs seen by apps --
> although some kinds of objects can be represented by both. Also notice that
> depending on the type of SturdyRef, the process for restoring is different:
> for "transient" objects located on a specific machine, the restorer connects
> directly to the target, but for stored object, the restorer connects to "the
> storage service" which it is introduced to independently at startup, and for
> external caps, it connects to "the gateways", etc.
>
> - For the public internet, you probably want a SturdyRef to encode a
> hostname and perhaps a pinned certificate list. Maybe it even encodes an
> HTTP URL, to which a Cap'n Proto session can be created over WebSocket or
> streaming HTTP/2. Additionally, it would encode some sort of object ID,
> probably as an AnyPointer. The target host would provide a bootstrap
> interface with a restore() method that takes this AnyPointer.
Yes, this is roughly what I have (though I encoded it as a simple
string URL, since it supports that form anyway).
It would be very useful to specify this so that different
implementations can talk to each other.
For example, I'd like to be able to cut-and-paste a URL from an OCaml
service and connect to it using the Python client.
> As you can see, in each case the format of a SturdyRef and the procedure for
> restoring it is completely different, so much so that it doesn't appear that
> any "standard" definition makes sense.
At the network level, yes. But at the application level it still makes
sense to have an abstract SturdyRef type in the schema language and in
the API I think. And it should be possible for applications to
exchange sturdy refs in messages without knowing what kind of network
their vats use.
> At some point I do want to spec out the "public internet" SturdyRef format
> and protocol. But, for now, I think implementations should leave SturdyRefs
> up to the application to define.
I don't see how this can work. For the public internet, I need to know
what to connect to, what protocol to speak (TCP, TLS, HTTP, etc) and
how to authenticate the peer. The object ID can be opaque, but the
rest must be known.
> On a side note, it seems like you were confused a bit by EZ RPC's mechanism
> for exporting capabilities by name. We deprecated this in favor of a
> singleton bootstrap interface because you can trivially implement the same
> thing by defining a bootstrap interface with a "restore(name)" method.
I could. But then I'm just replacing a somewhat standard interface
with a non-standard one that the other clients don't have built-in
support for. It doesn't seem like an improvement.
>> capnp://
sha-256:s16WV4JeGusAL_nTjvICi...@127.0.0.1:7000
>> email to
capnproto+...@googlegroups.com.
--
talex5 (GitHub/Twitter)
http://roscidus.com/blog/
GPG: 5DD5 8D70 899C 454A 966D 6A51 7513 3C8F 94F6 E0CC