Running a CCF Service

Starting the First Node

To create a new CCF network, the first node of the network should be started with the start option:

$ cchost --config /path/to/config/file
        graph LR;
    Uninitialized-- config -->Initialized;
    Initialized-- start -->PartOfNetwork;
    

The unique identifier of a CCF node is the hex-encoded string of the SHA-256 digest of the public key contained in its identity certificate (e.g. 50211327a77fc16dd2fba8fae5fffac3df909fceeb307cf804a4125ae2679007). This unique identifier should be used by operators and members to refer to this node with CCF (for example, when Trusting a New Node).

CCF nodes can be started by using IP Addresses (both IPv4 and IPv6 are supported) or by specifying a fully qualified domain name. If an FQDN is used then a dNSName subject alternative name should be specified as part of the node_certificate.subject_alt_names configuration entry. Once a DNS has been setup it will be possible to connect to the node over TLS by using the node’s domain name.

When starting up, the node generates its own key pair and outputs the unendorsed certificate associated with its public key at the location specified by the node_certificate_file configuration entry. The certificate of the freshly-created CCF network is also output at the location specified by the service_certificate_file configuration entry.

Note

The service certificate should be distributed to users and members to be used as the certificate authority (CA) when establishing a TLS connection with any of the nodes part of the CCF network. When using curl, this is passed as the --cacert argument.

The initial constitution scripts, member certificates, public encryption keys and data files as well as the initial service configuration should be set in the command.start section of the JSON configuration.

Once the first node is started, the network will be in its opening state and new nodes can join the network.

Adding a New Node to the Network

To add a new node to an existing opening network, other nodes should be started with the join option:

$ cchost --config /path/to/config/file
        graph LR;
    Uninitialized-- config -->Initialized;
    Initialized-- join -->Pending;
    Pending-- poll status -->Pending;
    Pending-- trusted -->PartOfNetwork;
    

The joining node takes the certificate of the existing network to join via service_certificate_file configuration entry and initiates an enclave-to-enclave TLS connection to an existing node of the network as specified by join.target_rpc_address configuration entry.

The join configuration option should be set in the command.join section of the JSON configuration.

A new node can only join an existing CCF network if its SGX quote is valid [1]. and runs an enclave application that is trusted by the consortium.

If the network has not yet been opened by members (see Opening the Network), the joining node becomes part of the network immediately. Otherwise, if the network has already been opened to users, members need to trust the joining node before it can become part of the network and participate in the consensus (see Trusting a New Node).

The Pending joining node automatically polls the service (interval configurable via join.retry_timeout configuration entry) until the members have successfully transitioned the node to the Trusted state. It is only then that the joining node transitions to the PartOfNetwork state and starts updating its ledger.

Tip

After the node has been trusted by members, operators should poll the GET /node/state endpoint on the newly added node, using the node’s self-signed certificate as TLS CA, until the {"state": "PartOfNetwork"} is reported. This status confirms that the replication of the ledger has started on this node.

Note

To accelerate the joining procedure, it is possible for new nodes to join from a snapshot. More information on snapshots here.

The following diagram summarises the steps that operators and members should follow to add a new node to an open CCF service, and wait for it to be trusted by the consortium and in state PartOfNetwork:

        sequenceDiagram
    participant Operators
    participant Members
    participant Node 0
    participant Node 1

    Note over Node 0: Already "PartOfNetwork" (rpc-address=ip0:port0)

    Operators->>+Node 1: cchost join (config: service_certificate_file=Service Certificate target_rpc_address=ip0:port0)

    Node 1->>+Node 0: Join request (includes quote)
    Node 0->>+Node 0: Verify Node 1 attestation
    Node 0-->>Node 1: "Pending" state

    loop Node 1 polls Node 0 (as per join.retry_timeout configuration entry)
        Node 1->>+Node 0: Poll for "Trusted" state
        Node 0-->>-Node 1: "Pending" state
    end

    Operators->>+Node 1: Poll GET /node/state for "PartOfNetwork" (using self-signed certificate as CA)
    Node 1-->>-Operators: "Pending" state

    Members->>+Node 0: transition_node_to_trusted proposal for Node 1 and votes
    Node 0-->>-Members: Proposal Accepted

    Operators->>+Node 1: Poll GET /node/state for "PartOfNetwork" (using self-signed certificate as CA)
    Node 1-->>-Operators: "Pending" state

    Node 1->>+Node 0: Poll for "Trusted" state
    Node 0-->>-Node 1: "Trusted" state (includes ledger secrets and service private key)

    Note over Node 1: State: "PartOfNetwork" <br/> Ledger replication started <br/> Application open to users

    loop Node 1 ledger replication
        Node 0->>+Node 1: Ledger replication
    end

    Operators->>+Node 1: Poll GET /node/state for "PartOfNetwork" (using self-signed certificate as CA)
    Node 1-->>-Operators: "PartOfNetwork" state

    loop Node 1 ledger replication
        Node 0->>+Node 1: Ledger replication
    end

    Node 1->>+Node 1: Observe own addition to store <br> Endorse TLS with service private key

    Note over Operators: Operators monitor progress of ledger replication
    Operators->>+Node 1: Poll GET /node/commit
    Node 1-->>-Operators: "commit": ...
    

Opening a Network to Users

Once a CCF network is successfully started and an acceptable number of nodes have joined, members should vote to open the network to Users via governance.

Virtual Mode

To run a CCF node on a system without hardware TEE support, or to debug an application, a virtual enclave should be used. To start a CCF node in virtual mode, the JSON configuration file should specify the path of a *.virtual.so enclave library and enclave.type should be set to "virtual".

Warning

Nodes started in virtual mode provide no security guarantees. They should never be used for production purposes.

Node and Service Data

To be able to better identify a specific service and its nodes, operators can specify arbitrary JSON data to attach to each service/node:

  • The optional node_data_json_file configuration entry specifies the path to a JSON file containing node-specific information, e.g. the pod identifier in a Kubernetes deployment. This data is recorded in the nodes.info table and accessible via the GET /node/network/nodes endpoint.

  • The optional service_data_json_file configuration entry specifies the path to a JSON file containing service-specific information, e.g. the timestamp at which the service started or the cluster identifier in a Kubernetes deployment. This data is recorded in the service.info table and accessible via the GET /node/network endpoint.

Footnotes