Hi There, Brief Introduction!

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.

  1. The hack of a JS bitcoin wallet exfiltrated funds.
  2. The extensibility of our platform was lacking.
  3. 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

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!


:wave: Hey Dan!

I think we have worked on the deterministic serialization of function references, but I wasn’t the one who had worked on it. I’m asking around to see if we might have solved it.

In the meantime, welcome! :grinning:

1 Like

Fun note: The Ethereum community is currently wrestling with an opcode CREATE2 which itself is designed to improve the determinism of their contract addresses. It’s clearly a hard problem.

Hello OCAP believers, I’m very much a novice in this arena, but love JS and am fascinated by Smart Contracts. My experiences working with Solidity and EOS left me feeling inept and defeated, so I’m encouraged to see this work to build abstractions that allow JS developers to build complex contracts using simple language primitives!

With regards to having a “deterministic way of re-assembling whatever identifiers I generated for these various functions”:

I got an idea while reading through erasure-protocol repository, in it they describe how they create a proof of ownership without revealing the data, like so:

proofHash = multihash(userAddress + salt + data)

Perhaps we could harness this concept to create proof of function, for example:

proofFunction = multihash(userAddress + functionName + functionDefinition + functionParameters)

functionDefinition and functionParameters and in my example could be string representations of the data (in JSON for example), or it could be the binary representation of the function and arguments.

This way you would be able to reconstruct the function and verify if it matches the proof in a deterministic way.

I have no idea if this is feasible of is just silly talk. I’m totally a newb here :slight_smile:


Welcome, @gamedevsam!

Welcome, @gamedevsam!

Since writing that, I now see two major approaches to this:

Building a JS runtime that persists its variables at every turn of the event loop, so that it can recover from a service interruption.

This means even functions that are created dynamically, like callbacks, can be resumed, and could maintain their persistent identifiers.

Currently that vision appears to be alive in the Swingset project for running natively. I’d also love if Swingset were compiled to web assembly, so we could get those environment features on the browser.

Building a JS userspace library for exposing function references over an async membrane.

This approach generally can most easily expose only functions that are hard-coded in that environment.

This is the general approach of CapnProto (not JS), and I also have a library I’ve been occasionally hacking on called capnode which is a general purpose JS RPC library for pre-authenticated connections (plenty to do over there if you peek :wink: )

Anyways, hope that gives you a few fun readings to explore your next steps!