ceramicnetwork / CIPs

The Ceramic Improvement Proposal repository
https://cips.ceramic.network/
MIT License
82 stars 22 forks source link

CIP-110 Ceramic Anchor Contract #110

Closed ukstv closed 1 year ago

ukstv commented 2 years ago
cip: 110
title: Ceramic Anchor Contract
author: Sergey Ukustov <sergey@ukstv.me>
discussions-to: https://github.com/ceramicnetwork/CIP/issues/110
status: Draft
category: Standards
type: Core
created: 2021-10-14
edited: 2021-10-14

Simple Summary

We can open other anchor service operators to participate in Ceramic anchoring using an allowlist as a smart contract on Ethereum blockchain.

Abstract

This improvement proposal presents a Ceramic Anchor Contract. It is a novel way to make anchors on Ethereum network.

Motivation

As of today, anchoring on Ceramic is done independently by each Ceramic Anchor Service (CAS). An anchor is a transaction from a wallet to itself with data, that represent a CID of a Merkle root.

While being low cost, such a construction presents a security risk, especially for Ceramic mainnet. A malicious CAS might withhold IPFS data necessary for proving an anchor (i.e. Merkle tree elements put on IPFS), thus making a Ceramic stream effectively invalid. We would like to make anchor services available for running by anybody, but this risk we would like to mitigate. Thus, until a validator network is in place, we would like to have a known set of trusted anchor services. We would like though the list to be open for anybody to join.

Specification

We can achieve that using a smart contract on Ethereum network (as our main network used for anchoring) that contains an allowlist of trusted anchor services. Only an allowed CAS can make an anchor transaction. The allowlist can be modified, preferrable by a DAO.

Contract Features

Implementation details

The contract should be written in Solidity language, using Truffle or Hardhat toolboxes. It might use OpenZeppelin library.

For "ownable" feature we are going to extend our contract Ownable from OpenZeppelin. The functionality provided there is good enough, so we do not elaborate on that topic further.

The allowlist is maintained as mapping (address => bool). We use two functions to modify the allowlist: addCas and removeCas, both emit a respective event:

mapping (address => bool) allowlist;

event DidAddCas(address indexed _service);
event DidRemoveCas(address indexed _service);

// Only owner can add to the allowlist
function addCas(address _service) public onlyOwner {
    allowlist[_service] = true;
    emit DidAddCas(_service);
}

// Removal can be performed by the owner or the service itself
function removeCas(address _service) public {
    require((owner() == _msgSender()) || (allowlist[_msgSender()] && _msgSender() === _service), "Caller is not allowed or the owner");
    delete allowlist[_service];
    emit DidRemoveCas(_service);
}

The "anchor" function can be called by an allowed service only. Its responsibility is limited to just emit an event:

// Only an address in the allowlist is allowed.
modifier onlyAllowed() {
    require(allowlist[_msgSender()], "Allowlist: caller is not allowed");
    _;
}

event DidAnchor(address indexed _service, bytes _root);

// Here _root is a byte representation of Merkle root CID.
function anchor(bytes calldata _root) public onlyAllowed {
    emit DidAnchor(_msgSender(), _root);
}

Anchoring Process

We maintain an authoritative list of anchoring contracts across Ethereum networks: Ropsten, Rinkeby, mainnet. This list is shared by CAS and Ceramic nodes.

CAS should use a contract on a network of choice for anchoring. When validating an anchor record, Ceramic node should check if a transaction happens on the authoritative contract, and the emitted event contains a merkle root.

Backwards Compatibility

Contract-based anchoring is not backwards compatible. We have to delineate between version of the anchors. We add a version property to AnchorCommit payload. Contract-based anchors use version: 1. If version is omitted, we expect the proof to be a raw transaction, and we check if it originated from one of the old well-known CAS addresses. After some time, to be defined later when CIP is accepted, Ceramic network only allows version: 1 proofs.

Rationale

An allowlist is for CAS instances, it allows them to do blockchain transactions. Thus, it is natural, that it is implemented as a blockchain smart contract.

Mainly we use Ethereum network now for anchoring, so Ethereum-based allowlist is a natural choice. It does not prevent to use other blockchains in future.

Single Ethereum transaction could be considered expensive. With the outlined design we effectively equalize the costs through multiple co-existing CAS instances.

Implementation

No implementation yet.

Security Considerations

Ideally, the contract should be independently audited to mitigate smart contract risks.

We consider allowed CAS to behave well, which is only enforced on social consensus layer until fully decentralized validators network is in place.

Copyright

Copyright and related rights waived via CC0.

stbrody commented 2 years ago

After some time, to be defined later when CIP is accepted, Ceramic network only allows version: 1 proofs.

We will probably always need to accept the old format anchors - otherwise we'll invalidate any streams created before the switch. As long as we only accept old-style AnchorCommits when the transaction is performed by one of the known trusted cas eth addresses, we should be able to continue to accept them forever without any loss of security.

stbrody commented 2 years ago

We could also only allow old-style anchors before a certain well-known blockNumber/blockTimestamp on ethereum based on when we made the switch to version:1 anchors.

oed commented 2 years ago

We could also only allow old-style anchors before a certain well-known blockNumber/blockTimestamp on ethereum based on when we made the switch to version:1 anchors.

Yes, this is what we should do!

ukstv commented 2 years ago

We could also only allow old-style anchors before a certain well-known blockNumber/blockTimestamp on ethereum based on when we made the switch to version:1 anchors.

Yes, this is what we should do!

This is what I implied when talking about time. We are not going to discard current anchors in any way.

ukstv commented 1 year ago

CIP-110 is now Final. Closing this issue.