Giter VIP home page Giter VIP logo

cap9's Introduction

cap9

Cap9 is a capability-based on-chain kernel for smart contracts. This repo contains kernel implementations for both evm, ewasm and substrate contracts.

CircleCI

Documentation

Development

  • EVM (Solidity) Lib – link
  • EWASM (Rust) Lib – link (WIP)
  • Substrate – (Coming Soon)

cap9's People

Contributors

jakeoshannessy avatar laboon avatar latrasis avatar road21 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cap9's Issues

Account#Call Capability

We need to include a test where:

  1. Creates procedure A, and a non-malicious Contract X
  2. Procedure A is given a account#call capability (type 0x09), that designates it is allowed to make a call to Contract X.
  3. Procedure A sends 1 eth to Contract X by invoking it's capability iff:

Storage#Read Capability

Tests should use #read(uint8 capId, uint location) in BeakerContract.sol

We need to include tests for a procedure that:

  1. Is given 1 storage read capability type 0x7 , that allows it to read an arbitrary, 32-byte value from address 0x07. This capability must be stored at index 0.
  2. Creates a 32 byte memory buffer, and invokes the read capability to write the value from address into that buffer.

Add padding for procedurePointers

Currently, in ProcedureTable#_getProcedureByKey, the keys are not seperated by procedure size, which means procedure chunks could potentially overlap. To fix this, we need to make sure that procedure pointers are seperated by at least the size of a procedure. (4 keys?).

Procedure Destruction

Based on #9, we need to decide how procedures can be owned and destroyed. This can either be done through some sort of code injection, or we simply don't handle ownership at all.

Comparison of EVM Languages Available

We need a language analysis report that compares the different languages available that are used currently for writing Smart Contracts.

Notably: Serpent, Solidity, etc

Reports should include:

  • An overview of tooling and maturity
  • An example erc20 token implementation
  • Pros and Cons experienced

Prioritize Issues

We need to figure out which issues are the most important to address.

Remove external kernel API

Currently there are many functions of the kernel that are exposed directly to external transactions. Most if not all of these functions should be limited by capabilities. The first stage would be to simply move these functions into an example entry procedure (with the necessary caps). This would allow for the same testing, but also force everything through the capability system.

The following functions are still exposed:

  • setEntryProcedure
  • createAnyProcedure
  • createProcedure
  • deleteProcedure
  • executeProcedure

These functions are exposed and should probably be removed, but are not critical for security:

  • listProcedures
  • returnRawProcedureTable
  • returnProcedureTable
  • getProcedure

Capability List

We need go through all the basic resources and actions involved during procedure execution.

Rudimentary Procedure Table

We need to create a rudimentary procedure table, it should be able to:

  • Receive Code
  • Validate Code
  • Create Contract
  • Store Contract Address by Created Id
  • Remove Stored Contract by Created Id
  • Delegate Call Contract on Demand from Id

Kernel Deployment

We need to address how a kernel instance is deployed, how it is instantiated and how we can test it.

Document Kernel Objects

Create a draft list of all the kernel objects we expect to encounter.

By kernel object we mean something that is held and controlled by the kernel. Examples include procedures and capabilities. It is usually expected that these objects are interacted with via some interface and/or capabilities.

Generalise Capabilities into List

Currently the write capability is hard coded, but we need to change that into a data structure that can handle multiple types of capabilities.

Procedure#Register Capability

Tests should use #proc_register(uint8 capId, bytes32 procId, address procAddr) in BeakerContract.sol

We need to include a test that:

  1. Includes Procedure A and Foreign Procedure B.
  2. Procedure A is designated a procedure register capability (type 0x4) that allows it to push a new procedure to the procedure table.
  3. Procedure A receives an address of Procedure B, and invokes the capability to add Procedure B into the procedure table.

Remove wiki

As we are doing the whitepaper in the docs/ folder the wiki can be removed for now. All information has been migrated to docs/.

Update design docs to simple capabilities

It looks like the current view on capabilities is a simple one where each procedure is assigned a list of capabilities. This precludes the need for minting, delegation, and the like. Currently, some of the design docs include this functionality. We need to update these design docs for this simpler system. Current work towards this is included in the design docs under Proposition B.

Procedure#Entry Capability

Tests should use library function #proc_entry(string id) in BeakerContract.sol

We need to include a test where:

  1. Creates Procedure A and Procedure B into the procedure table.
  2. Procedure A is designated as the Entry Procedure during kernel instantiation.
  3. Procedure A is also designated a procedure entry capability (type 0x6) that allows it to designate a new entry procedure from the procedure table given an id.
  4. Procedure B is not given any capabilities
  5. Procedure A changes Procedure B as the entry procedure, giving up it's position and does so by invoking it's procedure entry capability.

Gas#Recieved Capability

We need to include a test where:

  1. Creates a procedure A
  2. Procedure A is given a gas#received capability (type 0x10), that designates it is allowed to read how much gas it's has received.
  3. The kernel instance is sent 9000 gas and Procedure A reads how much gas it received using it's gas#received capability

Execute procedure syscall

We need to specify how to call a procedure from another procedure. I'm referring to this as a system call, as we need to work out the whole mechanism, not just the capability.

Concrete (i.e. byte-level) design allowing us to do one thing

We want to have the code and the format for a procedure to write an arbitrary, 32-byte value to address 0x07. This should be executed via a capability attached to a procedure. This will be the basis from which we extend to other capabilities.

Procedure#Delete_cap Capability

Tests must use #procedure_delete_cap(uint8 capId, string procId, uint8 targetCapId) in BeakerContract.sol

We need to include a test that:

  1. Creates Procedure A and Procedure B.
  2. Procedure A is given two capabilities: 1 storage write capability (type 0x8) for key 0xdeadbeef and a procedure delete_cap capability (type 0x2) that allows it to share one or more of it's capabilities from cap table to another procedure.
  3. Procedure B is given a storage write capability (type0x8) for key 0xdeadbeef, this write capability must be the same as Procedure A.
  4. Procedure B uses it's storage write capability to write a 32 byte value to key 0xdeadbeef from a memory buffer.
  5. Procedure A deletes the storage write capability of Procedure B by referencing it's own capability.
  6. Procedure B then tries to use it's storage capability to again write a 32 byte value to key 0xdeadbeef from a memory buffer but is rejected.

Ambiguity between mintable and invokable capabilities

Reading the current draft from docs/Usage.md, it's not clear to me how the user can clearly know which capability needs to be minted or invoked.

For example, when I see this:

let &cap2 = mint(&cap1, param)
let ret = invoke(&cap2,"data")

It's not clear when cap1 can be used to invoke or mint something. What happens if I invoke(&cap1, "data") ?

Procedure Endpoints as Objects

For procedure message passing, we have the option of making use of the ETH ABI as procedure endpoints, and thus explicit objects in the kernel, or not.

Whitepaper outline

What needs to go into the whitepaper? What design detail is needed and what isn't?

Rudimentary Memory Protection

When the Procedure table #9 runs a delegateCall, it may be vulnerable to jumps into it's kernel stack frame. To prevent this, during contract validation and creation, memory access must be restricted.

Factory#validate

To start, we need to validate an procedure for not having:

  • CALL
  • CALLCODE
  • DELEGATECALL
  • CREATE
  • SUICIDE

Procedure Execution with StaticCall

Background

When executing a procedure we need to make sure:

  1. Unprivileged State Access/Modifications are rejected.
  2. State Access using a valid capability is accepted.

Proposal

  1. When executing a procedure from the kernel we use STATICCALL instead of DELEGATECALL.
    When executing a procedure from kernel space:
  2. To prevent state changes instead of checking for opcodes, we rely on STATICCALL to prevent them at runtime.
  3. Whenever a procedure requires a kernel resource, it returns the current memory with a 64 byte header which includes: The capability invoked, argument location, input location, and next valid jump location within the procedure stack.
  4. If a kernel receives a valid invocation, it dispatches the requested resource, if the resource returns any data, the data is included into the input location. The procedure then reads the next jump location, and continues execution.

Considerations

As an example, when accessing SSTORE, this proposal incurs the additional cost of aSTATICCALL, it remains to be seen if it is cheaper to simply encapsulate an opcode than to do context switching.

Capability List: Seperate List per Capability Type

Following #55 and #44, procedure#clist is a heterogeneous list of capability types, and requires parsing in order to access a capability by index. This makes syscalls more expensive and also doesn't take advantage of a clist that could contain multiple capabilities of the same type and size.

In order for a procedure to contain multiple capabilities of the same type, we need to seperate the procedure#clist into a list of separate lists of homogenous capability types.

While this would make indexing faster, it brings additional complexity which needs to be addressed. This should be done after #44 in a separate PR.

Lifetime of Procedure Capabilities vs Process Capabilities

Currently, how a procedure c-list and process c-list interact is still ambiguous. I would additionally propose we define the lifetime of a capability: from creation to revocation. To elaborate, a capability in a procedure is born with a procedure being created, and is revoked when the procedure is destroyed. A capability in a process however can either live once per process or be stored within a procedure, but can still be hypothetically revoked.

Where does a minted capability point to?

During exec, when a caller mints a new capability for a callee, does the capability point to the caller's c-list or the callee's c-list? If the latter, why would this require the caller to pass on a pointer if the callee can simply lookup it's c-space?

Use two-stage procedure creation

Procedure creation should be 2 steps:

  1. Deploy the contract to the blockchain.
  2. Ask the kernel to verify and register it as a procedure.

Hybrid Ewasm Kernel + EVM procedures

Context:

With the upcoming adoption of the EWASM execution format, we need to come to a decision on which execution format to support in the near future.

Current development of the kernel prototype in EVM1 has been relatively smooth, but solidity has been proving itself difficult for more granular tasks and tests. This has lead to convoluted solutions and issues revolving custom memory alignments and storage addresses, namely #18 and #8.

EWASM on the other hand already has substantial toolchain support. Since it is a strict subset of the Wasm, debugging tools are already available (chrome, firefox) and can be written in rust as a compilation target in the form of pwasm.

In comparison with Solidity as a language, Rust can provide us substantially more granular control with better ergonomics.

Proposal:

Migrate to EWASM as our default target for the kernel, but support procedures targeting EVM1.

Pros:

  • Early start with EWASM support
  • Better Developer Ergonomics
  • Better Debugging tools
  • Can still support EVM1 format for procedures

Cons:

  • New language and unstable target (pwasm)
  • EWASM is not stable as a specification and may undergo substantial changes long term.
  • No guarantees EWASM will be adopted within this year.
  • Abandoning support for EVM1 within the kernel means we will only be able to demo our prototype on the kovan network until EWASM is fully supported.
  • Ewasm binaries currently are relatively large, which means we will face larger gas costs short-term. There are some tools available that might help with this.
  • Interaction between an EWASM parent and EVM1 child are yet to be stabilized.

Current Work:

See: https://github.com/Daolab/beakeros/tree/ewasm

Location of Procedure Table etc.

We've been defining storage capabilities of procedures based on address ranges, but we don't place the kernel storage (such as the procedure table) in a defined address range, therefore we cannot prevent access.

The kernel storage needs to be allocated in a defined range.

Factory#create

To start with we need to create a Factory contract that receives a sample contract instructions as payload and creates it.

Procedure#Push_Cap Capability

Tests must use #procedure_push_cap(uint8 capId, string procId) in BeakerContract.sol

We need to include a test that:

  1. Creates Procedure A and Procedure B.
  2. Procedure A is given two procedures: 1 storage write capability (type 0x7) for key 0xdeadbeef and a procedure push_cap capability (type 0x1) that allows it to share one or more of it's capabilities from cap table to another procedure.
  3. Procedure A shares it's storage write capability to Procedure B.
  4. Procedure B then uses it's new storage capability to write a 32 byte value to key 0xdeadbeef from a memory buffer.

Procedure#Delete Capability

Test should use #procedure_delete(uint8 capId, string procId) in BeakerContract.sol

We need to include a test that:

  1. Introduces Procedure A and Procedure B into the procedure table.
  2. Procedure A is designated a procedure delete capability (type 0x3) that allows it to delete Procedure B based on it's id.
  3. Procedure B is not given any capabilities.
  4. Procedure A removes Procedure B from the procedure table by invoking it's capability.

Log#Write Capability

We need to include a test that:

  1. Introduces Procedure A
  2. Procedure A is designated a log write capability (type 0x9) that allows it to log event from a memory buffer with 0xdeadbeef always as the first parameter.
  3. Procedure A stores Hello World into memory and invokes it's log capability to log 7HelloWorld as a result.

Procedure#Call Capability

We need to include a test that:

  1. Creates two procedures, procedure A and B
  2. Procedure A is given a procedure#call capability (type 0x2), that designates it is allowed to execute procedure B.
  3. Procedure B is given a storage#write capability (type 0x7), that designates it is allowed to write to address 0x7.
  4. Procedure A receives a 32 byte value, invokes it's capability to pass on the value to Procedure B, which stores the value at address 0x7.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.