Hi everybody,
I’d like to let you all know that I think you’re correct.
It seems increasingly clear to me that ocaps are a missing piece from computing, and I applaud everyone here for having reached this conclusion.
I had been chewing on some deep intuitive basics about trust and risk for years and finally articulated it late 2017 well enough to start blogging about how I thought things might unfold with this new technology:
I’m a founder and lead developer of MetaMask, a browser extension that itself carries some user-prompting crypto functions (not quite yet capabilities), and several issues have started leading us to converge on ocaps.
- The hack of a JS bitcoin wallet exfiltrated funds.
- The extensibility of our platform was lacking.
- The scalability of the blockchain is holding back developers.
I currently believe all three of these major issues are handled head-on by ocaps. Imagine my terror when I see people like Mark Miller having been advocating for them for the last 20 years! Surely we don’t need another 20, right?
I initially made a minimum-viable local-capability system in a branch of MetaMask by writing https://github.com/MetaMask/json-rpc-capabilities-middleware, and the pragmatist in me says ship it!
I had been looking at some of Mark’s talks showing how Promises were intended to be abstractions of capabilities, and so I started thinking a promise-passing version of dnode might be a good path.
I was able to pretty quickly whip-up a promises-over-dnode project that I’m tentatively calling capnode, but it quickly hit serious limitations:
- Dnode only passes functions in one direction, one time, while I want to freely pass function references (capabilities) back and forth over a connection.
- This implied needing authorization at another layer, but whenever I thought of auth, it came back to the keys.
I had sketched up a table of some of the options I was considering:
Ocap Types | Is provably safe and isolated. | Can be passed to pages from the background. | Sites can delegate permissions to each other, which can be used even when the delegating site is not open. | Sites can delegate permissions to each other even when the user isn’t connected to them. | Delegations Do not create a memory leak on the host. | Can be passed directly to an Ethereum smart contract. |
---|---|---|---|---|---|---|
JavaScript | No | No | No | No | No | No |
SES | Yes | No | No | No | No | No |
Local “Soft” Table with implicit JS delegation | Yes | Yes | No | No | No | No |
Local “Soft” Table with explicit delegation table. | Yes | Yes | Yes | No | No | No |
Off-chain Crypto Hard Macaroon | Yes | Yes | Yes | Yes | No | No |
Off-chain Crypto Hard Signature chain like ocap-ld | Yes | Yes | Yes | Yes | Yes | No |
On-chain crypto hard w/ signTypedData | Yes | Yes | Yes | Yes | Yes | Yes |
Since my project is an Ethereum client first, the ability to submit these capabilities on-chain in an efficient format was a constant appeal.
Ocap-LD was an early obvious consideration, with Mark as a co-author, but the only JS implementation severely lacks docs, and only seems to support RSA keys, and was really hard to get into.
I also briefly experimented with doing ocap chains over ipld, which is probably still a good idea regardless of the schema (just need to PR a schema to IPLD), but ultimately was deterred by the fact that it seemed so tightly tied to IPFS, whose JS client is fairly unstable, and also made all the capabilities seemingly fully public, which lost some of the private advantages of them to me.
Mid last year, MetaMask finally implemented an Ethereum improvement proposal for an object signature proposal known as EIP 712, which is designed for both human readable and efficiently blockchain-consumable binary signature formats, and when I tried that out, I have so far been met with pretty rapid success, probably in part because I am already familiar with the tooling around it.
I am borrowing as much verbiage as possible from ocap-ld, and following its schema, but for now am experimenting with this EIP-712-derived ocap format, and as of this afternoon, have basic signing and verification working.
Next steps would be:
- Serializing/deserializing promise-function-containing-objects (need a catchier name).
One thing that really caught me up today was deterministic identifiers for the functions passed in. Let’s imagine I initialize a JS ocap server with an object like:
var server = Ocap({
foo: async() => 'bar!',
requestAccess: async () => {
if (prompt.user('may they?')) {
return secretDoorFunction
}
}
})
httpServer.onConnect(server.handleRequest)
Now I may run this server for a while, and I may give out several different references to the secretDoorFunction
, but once my machine shuts down and starts up again, I need a deterministic way of re-assembling whatever identifiers I generated for these various functions!
From perusing the topics, it looks like someone here has thought about just about every aspect of this, and I’m sure I’ll get through this just to hit another issue, but for now, I’ll just open up and ask how anyone here is thinking about deterministic serialization of function references.
Anyways, thanks a lot! Can’t wait to build the new world with you!
PS. I’m also pretty bewildered by one recurring theme in Mark’s talks, where he passes a pending promise as an argument to another promise? I have not gotten my head around what that means in a serialized ocap sense, would love pointers to how that would be constructed! Thanks!