Reposted from here.
As I just presented on the GitCoin live stream.
Ethereum Object Capabilities
Here I will make the case that Object Capabilities (ocaps) represent a key atomic unit of composition, security, and versatile scalability (both computational and social) that is urgently missing from the Ethereum ecosystem, and merits a coordinated effort on behalf of Ethereum developers (and most blockchain developers).
What are Ocaps?
From Wikipedia, an Object Capability is:
- an unforgeable reference (in the sense of object references or protected pointers) that can be sent in messages.
- a message that specifies the operation to be performed.
Furthermore, objects can only communicate by message sending, and capabilities can only be obtained by either:
- initial conditions
i.e., all permissions are fully explicit and delegatable.
One way to think of an ocap is as a first-class object reference.
Another way is a signed message that grants the recipient the power to call a function, which itself can be signed and delegated.
Ocaps as Power
Just think of an Ocap as a power.
It’s a power to do a given thing, given some constraints.
It could be the key to your house, or the right to enter a concert, or some tokens to buy pizza.
But this isn’t just a transferrable power like a physical object, it’s also sharable, or delegatable: Multiple people can wield the same finite power, and you can even delegate a power with new limitations, or “caveats”.
Prior Ethereum Art That Resembles Ocaps
This pattern is already visible repeatedly throughout the ecosystem, although it is not generalized and in turn lacks many key features, but we can look at them now to establish their usefulness, and later we’ll revisit them to see how they could be improved by more deliberate ocap architecture.
The Token Allowance Method
The original inter-contract permission allowed users on exchanges to trigger trades without locking their funds into an exchange contract.
A MetaTransaction is a signed message that grants another account, or “relayer” the power to initiate a transaction on your behalf, usually in exchange for a fee.
0x Protocol Relayers
In the 0x Protocol, an “order” is a signed off-chain message that grants any holder the option to initiate a trade at a rate established in the message, in exchange for a fee to the relayer.
A subscription is a granted permission to another account to withdraw at a pre-defined rate.
Each state channel update can be defined as an off-chain capability for either member of the channel to settle the balance of that channel after a challenge period.
Plasma chains imbue their participants with off-chain message that grant them the capability to trigger a withdraw function, again which has the caveat of a challenge period.
Delegation and Attenuation
If you have a function reference, you can call that function, but you can also pass it to someone else (like a smart contract), as delegation.
When delegating an ocap, you also have the opportunity to add arbitrary caveats, or attenuations.
For example, if I have permission to open my front door, I could rent out my house and give my kooky friend permission to open my front door but only this weekend.
This series of permissions can be represented as a chain of signed messages off-chain, or it can be represented as a chain of permissioned contracts on-chain. There are probably countless possible constructions, so there is probably some value to establish baseline patterns that more sophisticated methods can be built on top of.
If we imagine each person and entity has a contract account capable of granting the permission to send transactions to new contracts. This is exactly how the Gnosis SAFE module system works, but the pattern should work with any contract capable of delegating sending permission.
We can easily represent the same chain of decreasingly permitted contracts as a series of off-chain messages, in a similar pattern to counterfactual state channels.
These messages would only need to be submitted to the door at the time of redemption. A reference to a message would also need to be submitted in order to revoke it.
Some types of delegations can include state, and in those cases, each delegating message would need to result in a deterministically addressed on-chain entity, likely a good opportunity to use the CREATE2 opcode.
For example, a delegated spending permission would always need to keep track of the amount withdrawn using it:
This issue was discussed in the past when discussing how tokens could be minted off-chain.
Note that as many have observed before, the blockchain is only needed for revoking and limiting permissions (“Blockchain as supreme court”). Extending permissions can happen entirely off-chain, and be consistently described in this pattern, establishing a path for blockchain-minimized development patterns.
Revisiting Prior Art
If the earlier examples used ocaps instead of bespoke off-chain messages, what would be different? Here are a few ideas off the top of my head, there are surely many more benefits.
The Token Allowance Method
If tokens included a transitive, off-chain allowance message, it would allow similar interactions as the current model, but making the setup transaction optional (less on-chain activity, transaction only mandatory on redemption), and also delegatable, which would almost inevitably provide some extensible usefulness.
Sites promising to pay for transactions on a user’s behalf could grant gas limits to the user, without locking up funds on a user’s behalf.
Sites could also delegate explicit gas delegation limits to different sybil verification strategies, so that if one were exploited, it would not drain the entire pool.
Additionally, the ability to delegate the permission to pay gas is a great way for users to invite their friends and bypass the “first crypto acquisition” onboarding problem. This benefit is transitive, and so arbitrary graphs of friends could be invited to use the network from a common pool of Ether.
0x Protocol Relayers
If expressed as delegatable ocaps, 0x orders could be issued to multiple order books simultaneously, and could be delegated multiple hops of order pools, each receiving their own commissions.
Subscriptions could be created with an off-chain message, and only need to touch the blockchain at the time of a withdraw or redaction.
Additionally, subscriptions represented as ocaps would also be delegatable, and so a subscription service could itself subscribe to services with its own subscriptions. This eliminates capital lockup along a subscription supply chain, allowing more efficient allocation of future capital.
As long as the root account incorporates a challenge period before it can withdraw the related funds, a state channel could be created entirely counterfactually. This would mean new participants could be added dynamically, and even signing rights could be freely delegated to external services, even incorporating validation fees, all dynamically added to the live channel without checking into the blockchain.
After the state channel example it should be clear that highly dynamic ocap accounts with a challenge period can already evolve into something resembling a Plasma chain. I think the ability for a validator to freely delegate their validation rights to another key or another combination of keys is already a pretty cool new feature.
Since funds in this case can also be sent to a counterfactually-instantiated account (one not published yet), funds on a plasma chain could be recursively deposited into a arbitrary sub-chains with their own withdraw periods, either state channels or tries of plasma chains.
Weight on Chain
One concern is that redeeming long chains of delegated ocaps can be expensive to redeem on chain, but that is only true in the most rudimentary case.
This could be addressed either with a challenge period in the style of state channels (allowing incomplete proofs), or with more efficient cryptography like zk-rollup.
The key message I’d like to communicate here is that the underlying security model is one worth pursuing, not that a specific implementation is ideal.
Many current layer-2 scaling strategies are plagued by data availability concerns. In an ocap architecture, the storage is always aligned with the agent who has value at stake. This means every piece of data has incentive equal to its value to store it, and in turn data availability becomes easier to address, since the actor incentivized to store the data can now choose from any solution available to them to keep their capabilities persistent.
Relationship to the Actor Model
Since each permission is granted between discreet stateful entities that represent a atomic sets of permissions, the Object Capability model is well known to closely map to the Actor Model, a model of computation that is optimal for sharding and scalability.
Here’s a recent article by Brooklyn Zelenka on how the actor model could improve smart contract architecture for Ethereum:
The Role of The Wallet
The wallet will play a key role in allowing people to connect to the apps, services, and entites they want to while exposing the least possible risk, and issuing capabilities is an ideal composition pattern for this kind of log-in flow:
- Keeping as much off chain as possible.
- Granting as little permission as needed.
- Allowing the user to revoke permissions at ay time.
- Allowing the service to freely internally delegate its permissions however it needs to.
Making ACLs Look Silly
A number of current Ethereum projects are starting to build complex security models on top of Access Control Lists (ACLs), which are essentially The Alternative to Object Capabilities, which are historically easier to invent, and so dominant, but less powerful.
For one thing, delegation doesn’t really work in the ACL model. Every time you want to grant a permission, you end up defining a new permission for granting a permission, but who grants the granting permission? And so many ACLs end up being silly lists of things like:
By embracing the natural law of transitive delegation, ocaps solve permission moderation in a pattern that naturally scales but is gracefully revocable by branch of broken trust at any time.
Also, ACLs are harder to code securely. Correctly writing ACL code requires code reviewers noticing the absence of enforcement, like a missing onlyOwner modifier, while ocaps invert the pattern, aligning authorization with access, so that access to a function becomes synonymous with permission to use it.
Crowdfunding and DAOs
There is a lot of work being done on sophisticated models of voting and allocating funds using on-chain entities.
Allowing agents to designate spending limits to other agents, and the ability to transitively delegate those allowances is a highly liquid, versatile, and composable way to allow groups of people to pool their resources for common causes.
It may sound simple, but that doesn’t mean it isn’t incredibly powerful!
Since caveats are the restrictions on calling a given method, the caveat format is worth deeply considering.
Ideally an account that is capable of issuing ocaps is also capable of interpreting a wide variety of caveats. Some of them may be efficient to express (few bytes), while others might be superior in their open ended nature.
For the sake of a minimum viable product, I would probably recommend a few efficiently encoded caveats as early ones:
- Restrict to method name
- Restrict to time period
- Restrict parameter to total sum (spending limit)
- Restrict parameter to amount over time (subscription)
- Restrict calling without challenge period (state channels)
Beyond these versatile cases, there should probably also be one open-ended but expensive tool, and this caveat would result in publishing its included bytecode as a new smart contract, which could enforce its own policies arbitrarily, potentially even relying on external state.
Note: Any stateful caveat would result in some state being published to the redeeming platform, and it is an exercise to the community whether multiple limits should reside within the same contract or multiple “actors”, although I think I know what Brooklyn would say!
Challenges at the VM/Language Layer
The EVM 1.x is single-threaded and all calls are synchronous. A true ocap/actor-model architecture requires a message queue for async invocations, and so may be a valuable consideration for Ethereum 2.0.
await sendToken(recipient, amount);
Fun fact: Promises were invented for the E-language, an ocap-centric language by Mark Miller.
The most basic approach to this would involve signatures on every delegation, but to allow inter-contract communication, there is an opportunity to make message authentication more efficient by being modular.
Once authentication is abstracted out of the message itself, this same message-passing pattern could become even more gracefully composable with remote-system oracles, relays, and inter-chain networks.
Write your code once, interact with anything!
Allows networks of accounts (people/programs) to dynamically allocate their resources to the other agents they trust, in proportion to that trust.
Looking for Contributors!
If you’re interested in helping guide Ethereum towards this secure, extensible, and human centric model, get in touch!
Whether you’re looking for a job or just to do a couple bounty contributions, I’m hoping we can get all willing and able hands on deck for this cause.
- Reentrancy attacks could be eliminated with Object Capabilities
- A video intro to Ocaps
- Ocap-LD: A JSON based Ocap W3C proposal
- Cap’n Proto a highly efficient binary capability serialization format.
- A previous description of off-chain spending permissions
- Capabul: A blog full of my thoughts on the social implications of this pattern
- An example ocap-ld like object in the EIP-712 format
- Promises are Probably Older Than You (NG-conf talk)
- Actor Factor - The Actor Model in Blockchains.
- Liquid Liberal Radicalism - Ocaps applied to Liberal Radicalism.
- Minimum Viable Consensus with Object Capabilities
Mark Miller and his team at Agoric has been truly leading the charge towards ocaps for the last decade or two: