This section describes key Obscuro component designs.
This section covers the various cryptographic techniques used by Obscuro.
CPU manufacturers provision every TEE with one or multiple keys, the Enclave Key (EK). These keys are used for digitally signing messages and identifying a TEE. They are also used for encrypting data that only that particular hardware TEE can decrypt. To achieve the goals of a collaborative, decentralised network like Obscuro, all the TEEs have to work on the same set of transactions, which means they must all decrypt them.
The first enclave, called the Genesis Enclave, generates a 256bit random byte array called the Master Seed inside the encrypted memory space. It encrypts this seed with the EK and sends it to the Management Contract to be stored there, as well as storing it locally on the host server.
Sharing the Master Seed
After proving their attestation, subsequent nodes receive that secret Master Seed encrypted with their key. The medium over which they receive the data is the Management Contract to ensure maximum data availability.
Before obtaining the shared secret, the L2 nodes must attest that they are running a valid version of the contract execution environment on a valid CPU.
Note: The solution assumes that attestation verification can be implemented efficiently as part of the Management Contract. This is the ideal solution since it makes the contract the root of trust for the L2 network.
The sequence for node registration is shown in the following diagram:
An L2 node invokes a method on the Management Contract to submit their attestation, verifying it and saving this request. Then, another L2 node (which already holds the secret key inside its enclave) responds by updating this record with the shared secret encrypted using the public key of the new TEE. Whichever existing L2 node replies first, signed by the enclave to guarantee knowledge of the secret, receives a reward.
Note: This solves several problems; the Management Contract provides a well-known central registration point on the Ethereum network, which can store the L2 shared secret in public with very high availability, and existing L2 nodes are compensated for their infrastructure and L1 gas costs to onboard new nodes.
The TEEs use the shared secret to generate further asymmetric and symmetric keys used by users to encrypt transactions and by the enclaves themselves to encrypt the content of the rollups.
Each enclave uses this master entropy to generate additional keys deterministically:
- A public/private key pair is used as the identity of the network. The public key is published to L1 and used by clients to encrypt the signed Obscuro transactions and is referred to as Obscuro_Public_Key
- A set of symmetric keys used by the TEEs to encrypt the transactions which will stored on the L1 blockchain in rollups.
Note: When submitting a rollup, each enclave signs it with the key found in their attestation (the _AK)._
One of the explicit design goals of Obscuro is to help application developers achieve their privacy requirements while giving them the tooling to disincentivise their users from using the application for illegal behaviour such as money laundering.
When deploying a contract to Obscuro, the developer has to choose one of the predefined revealing options:
- XS - 12 seconds (1 block)
- S - 1 hour (3600/12 = 300 blocks)
- M - 1 day (24 * 3600/12 = 7200 blocks)
- L - 1 month
- XL - 1 year
Note: These periods are counted in L1 blocks and are indicative.
One of these options is chosen by default for applications that do not explicitly specify one. Based on the chosen period, transactions submitted to that application can be decrypted by anyone after that time delay.
The protocol deterministically derives 5 symmetric encryption keys for each rollup, derived from the master seed, the reveal option, the running counter for that option, and the block height, such that all TEEs in possession of the master secret can calculate the same encryption key.
For example, application FooBar has a reveal setting of M (1 day). Alice submits a transaction (encrypted with the Obscuro_Public_Key) Tx1 on the 1st of February and another Tx2 on the 2nd of February. Inside the TEE, they are decrypted and executed. When the rollup is generated, all transactions sent to applications with the same reveal option are bundled together by the Aggregator, compressed, and encrypted with the Encryption_Key(Master_Seed, Reveal_Option, Counter, Block_Height).
The transaction blob is formed by concatenating all the encrypted intervals without any delimiter to prevent information from leaking. Then, separately from the transaction blob, a data structure is created containing each option’s start (index) position. This map is also added to the rollup after being encrypted with a separate key that is not revealed.
This is depicted in the following diagram:
Note that the predefined reveal periods are preferable to each application choosing a custom period, as it simplifies computation and the number of keys that have to be managed.
The mechanism described above ensures that Obscuro transactions are encrypted with different keys, which can be revealed independently.
The other piece of the puzzle is the mechanism that controls the actual reveal process. On a high level, the platform needs a reliable way to measure the time that cannot be gamed by a malicious host owner.
The L1 blocks can be used as a reliable measure of average time. The rule is that after enough blocks have been added on top of the block that includes the rollup with the encrypted transactions, any user can request the encryption key and the position of the transactions they are entitled to view from the TEE of any Obscuro node.
A malicious node operator wanting to have a peek at transactions before the designated time has passed can try to fast-forward time by creating an Ethereum fork and mining blocks with well-chosen timestamps such that difficulty keeps decreasing.
The solution to this problem is straightforward. Obscuro TEEs fully understand the Ethereum protocol and receive all L1 blocks as part of the POBI protocol, which allows them to verify that the blocks are valid, but they cannot know wheter this is the canonical Ethereum chain or a malicious fork designed to fast-forward time. To address this, Obscuro hard-codes a minimum difficulty lower than the average network difficulty for the last year, but much higher than any single actor can achieve. This will prevent the node operator from speeding up time.
Obscuro makes the same choices as Ethereum for hashing and signing algorithms and uses the same elliptic curve.
Communication with TEEs and the encryption algorithms are not yet defined.
Note: There might be a more efficient way to achieve the same high-level goals, and we are considering different other options.
Obscuro is an account-based L2 decentralised ledger system similar to the L1 Ethereum blockchain, where the state is calculated independently by each node based on the canonical list of transactions and stored as a Patricia Trie in each rollup. Each node processes all prior transactions to establish the current state (full sync), and optimised sync methods (e.g. fast sync) will likely be supported. One significant difference is that the account balances can only be calculated inside the TEEs and are only revealed under certain conditions. The model is not described further in this paper because it is the same as Ethereum Accounts.
The transaction and smart contract formats are similar to Ethereum, with a few differences introduced by the confidentiality requirements.
Smart Contracts and the Obscuro VM
Obscuro application developers will write smart contracts in a familiar programming language using familiar blockchain tools and abstractions. Due to data privacy concerns, existing smart contracts will have to change before deploying them to Obscuro.
To implement these requirements, Obscuro supports a runtime largely compatible with the Ethereum Virtual Machine (EVM) and is derived from an existing implementation such as Geth, the canonical client of the Ethereum protocol.
On a high level, the Obscuro Virtual Machine (OVM) will be almost identical to the EVM, but there are significant differences behind the scenes between the data structures used by Ethereum and the ones used by Obscuro. The rollup structure also differs significantly from the Ethereum block structure as it contains encrypted transactions, plaintext withdrawal instructions, plaintext events, references to L1 blocks, and more. The OVM will eventually introduce new abstractions and primitives to reflect the data privacy requirements and implement data isolation where it is needed. One last significant difference from the EVM is the implementation of the Obscuro cryptography requirements.
State Confidentiality between Smart contracts
The main goal of Obscuro is to protect user data. If smart contracts were wholly isolated from each other, it would be easy to define data access rules.
Contract composition introduces significant complexity. DeFi enjoys massive success thanks to the ability of contracts to be combined in serendipitous ways not predicted by the contract creator, and Obscuro intends to replicate that.
For example, one contract might have been written to reveal information for the caller’s eyes only in an encrypted response. But if the caller is another contract, that wrapping contract might turn the response into a public broadcast event, visible to everyone.
This area is still under active research. The first version of Obscuro will rely on application developers to check programmatically who can call different functions and what data they should receive, and therefore developers should reason about what could happen if their contract is called by a contract that they don’t control.
For subsequent versions, Obscuro explores the following concepts:
- Each contract can declaratively whitelist contracts that can access different functions.
- Automatically propagate access. For example, if Account.getBalance() can be invoked only by the owner, it means that any contract that invokes this has to originate from a message signed by the owner. This solution sounds appealing, but it needs more research to determine if this mechanism prevents useful use cases.
Wallets and Transaction Submission
User wallets create transactions encrypted with the Obscuro public key. Only valid TEEs (i.e. Aggregators and Verifiers) in possession of the Master Seed can decrypt, execute, and see the resulting state. Still, end-users who submitted a transaction must be able to receive the result and query the balance.
A traditional wallet connected to a node on a public blockchain can read the balance of any account and display it to the user. For a similar user experience, Obscuro-enabled wallets need to submit signed requests to L2 nodes and receive responses that they can display to the user. The responses need to be encrypted with the user key and have to be cryptographic proofs linking the balance to a rollup.
Validity verification of such proofs can be done by first checking the TEE signature and then by checking that the rollup is on the canonical chain of both the L2 and the L1 chains.
Smart Contract Types
Since all data is temporarily private, and smart contracts are just data, the Obscuro model supports two types of smart contracts.
Public contracts, which are equivalent to the Ethereum smart contracts in the sense that the source code will be available online, and anyone can build them and compare the hash of the bytecode against the address they are sending commands to.
Private contracts, for which the developer has not published the source code. These can be used for custom logic like arbitration where the developer intends to keep the profit making strategy hidden from competitors.
On the L1 network, several conventional Ethereum contracts act together to form a Management Contract.
This contract is the gatekeeper for the protocol. Therefore, any node wishing to join Obscuro must interact with this contract and prove it is valid.
- It registers L2 nodes, verifies their TEE attestation, and manages their stakes. (Stakes are required for the Aggregators who publish rollups as an incentive to follow the protocol.)
- It manages the TEE attestation requirements. This means that the governance of the contract can decide which enclave code is approved to join.
- It manages the L2 TEEs’ shared secret key to be available in case of L2 node failure. The L1 acts as the ultimate high availability storage. Note: This is expanded in the Cryptography section.
- It keeps a list of URLs (or IP addresses) for all Aggregators. The use of URLs allows for the underlying IP address to be changed. Verifiers do not stake, and are not a gossip recipient, so their address is not recorded, but they must register in order to attest a correct TEE and to be able to collect rewards.
This contract interacts with the Aggregators.
- It determines whether to accept blocks of transactions submitted by an L2 node. The Rollup contract can only accept a rollup from an Aggregator with a stake and valid attestation, and it checks that the signature of the rollup generated in the TEE matches the Obscuro_Public_Key registered by the L2 node.
- It stores the encrypted L2 transactions in an efficient format.
This contract is essential for the solution’s security since all value deposited by end-users is locked in this bridge.
- It acts as a pool where people can deposit assets, like fungible or non-fungible ERC tokens, made available as wrapped tokens to use on the Obscuro network and can be withdrawn on demand back to an L1.
- In case of conflicting forks in the rollup chain, it must delay withdrawals until one fork expires or enter a procedure to discover which fork is valid. This is covered in more detail in Withdrawals.
- It may be extended to manage liquidity yields.