[][src]Module exonum::runtime

Common building blocks that compose runtimes for the Exonum blockchain.

Each runtime contains specific services that execute transactions, process events, provide user APIs, etc. A unified dispatcher redirects all the calls and requests to an appropriate runtime environment. Thus, a blockchain interacts with the dispatcher, and not with specific runtime instances.

Artifacts

An artifact creates service instances similar to classes in object-oriented programming. Artifacts reflect the assumption that deploying business logic onto the blockchain may take a long time, may fail, end up with differing results on different nodes, etc. Thus, artifacts decouple the complex deployment of the business logic from its instantiation (which we assume is simple / non-fallible).

Depending on the runtime, an artifact may have an additional specification required for its deployment; e.g., files to be compiled.

Each runtime has its own artifacts registry. Users can create services from the stored artifacts. An artifact identifier is required by the runtime to construct service instances. In other words, an artifact identifier is similar to a class name, and a specific service instance - to a class instance. A single artifact may be used to instantiate zero or more services.

The format of the artifact ID is uniform across runtimes - it is essentially a string. But the runtime may customize artifact deployment via runtime-specific deployment arguments.

Artifact Lifecycle

  1. An artifact is assembled in a way specific to the runtime. For example, an artifact may be compiled from sources and packaged using an automated build system.

  2. The artifact with the service is deployed on the blockchain. The decision to deploy the artifact and the deployment spec are usually performed by the blockchain administrators. The corresponding logic is customizable via the supervisor service. What deployment entails depends on the runtime; e.g., the artifact may be downloaded by each Exonum node, verified for integrity and then added into the execution environment.

  3. For each node, an artifact may be deployed either asynchronously or synchronously, that is in a blocking manner. The supervisor usually first commands a node to deploy the artifact asynchronously via Mailbox, once the decision to start deployment is reached by the blockchain administrators. Asynchronous deployment speed and outcome may differ among nodes.

  4. The supervisor translates the local deployment outcomes into a consensus-agreed result. For example, the supervisor may collect confirmations from the validator nodes that have successfully deployed the artifact. Once all the validator nodes have sent their confirmations, the artifact is committed. As a part of the service logic, artifact commitment is completely deterministic, agreed via consensus, and occurs at the same blockchain height for all nodes in the network.

  5. Once the artifact is committed, every node in the network must have it deployed in order to continue functioning. If a node has not deployed the artifact previously, deployment becomes blocking. The node does not participate in consensus or block processing until the deployment is completed successfully. If the deployment is unsuccessful, the node stops indefinitely. The deployment confirmation mechanics is built into the supervisor. Thus, it is reasonable to assume that a deployment failure at this stage is local to the node and could be fixed by the node admin.

  6. If the artifact is not associated with any services, it can be unloaded. Unloading the artifact may free resources associated with it in the corresponding runtime. Like other lifecycle events, unloading an artifact is controlled by the supervisor service.

Service Lifecycle

  1. Once the artifact is committed, it is possible to instantiate the corresponding service. Each instantiation request contains an ID of the previously deployed artifact, a string instance ID, and instantiation arguments in a binary encoding (by convention, Protobuf). As with the artifacts, the logic that controls instantiation is encapsulated in the supervisor service.

  2. During instantiation the service gets a numeric ID, which is used to reference the service in transactions. The runtime can execute initialization logic defined in the service artifact; e.g., the service may store some initial data in the storage, check service dependencies, etc. If the service (or the enclosing runtime) signals that the initialization failed, the service is considered not instantiated.

  3. Once the service is instantiated, it can process transactions and interact with the external users in other ways. Different services instantiated from the same artifact are independent and have separate blockchain storages. Users can distinguish services by their IDs; both numeric and string IDs are unique within a blockchain. (Note that the transition to the "active" state is not immediate; see Service State Transitions section below.)

  4. Active service instances can be stopped or frozen by a corresponding request to the dispatcher.

The dispatcher is responsible for persisting artifacts and services across node restarts.

A stopped service no longer participates in business logic, i.e., it does not process transactions or hooks, and does not interact with the users in any way. Service data becomes unavailable for the other services, but still exists. The service name and identifier remain reserved for the stopped service and can't be used again for adding new services.

Frozen service state is similar to the stopped one, except the service state can be read both by internal readers (other services) and external ones (HTTP API handlers).

Service Hooks

Each active service is called before any transactions in the block are processed; we call this before_transactions hook. The service may modify the blockchain state in this hook. Likewise, each active service is called after all transactions in the block have been processed (we call this after_transactions hook). These calls are quite similar to transactions:

  • Each call is isolated
  • Service logic may return an error, meaning that all state changes made within the hook are rolled back
  • The service may call other services within the hook

Service State Transitions

Transitions between service states (including service creation) occur once the block with the transition is committed; the effect of a transition is not immediate. This means that, for example, an instantiated service cannot process transactions or internal calls in the block with instantiation, but can in the following block. Likewise, the service hooks (before_transactions / after_transactions) are not called in the block with service instantiation.

When the service is stopped or frozen, the reverse is true:

  • The service continues processing transactions until the end of the block containing the stop command
  • The service hooks are called for the service in this block

Transaction Lifecycle

  1. An Exonum client creates a transaction message which includes two parts. The first part is the CallInfo - information about a method to call. The second part is the serialized method parameters as a payload. The client then signs the message using the Ed25519 signature system.

  2. The client transmits the message to one of the Exonum nodes in the network.

  3. The node verifies correctness of the transaction signature and retransmits it to the other network nodes if it is correct.

  4. When the consensus algorithm finds a feasible candidate for the next block of transactions, transactions in this block are passed to the dispatcher for execution.

  5. The dispatcher uses a lookup table to find the corresponding Runtime for each transaction by the instance_id recorded in the transaction message. If the corresponding runtime exists, the dispatcher passes the transaction into this runtime for immediate execution.

  6. After execution the transaction execution status is written into the blockchain.

Data Migration Lifecycle

Service data can be migrated to a newer version of the service artifact. See migrations module docs for details.

Supervisor Service

A supervisor service is a service that has additional privileges. This service allows deploying artifacts and instantiating new services after the blockchain is launched and running. Moreover the Supervisor service allows update the configuration or stop the active service instances. Other than that, it looks like an ordinary service.

To enable adding new artifacts / services to the blockchain after its start, the supervisor must be one of the builtin service instances.

The supervisor service is distinguished by its numerical ID, which must be set to SUPERVISOR_INSTANCE_ID. Services may assume that transactions originating from the supervisor service are authorized by the blockchain administrators. This can be used in services: if a certain transaction originates from a service with SUPERVISOR_INSTANCE_ID, it is authorized by the administrators.

See Also

Modules

migrations

Data migration tools.

oneshot

A channel for sending a deployment status between threads.

versioning

Versioning tools for Exonum artifacts.

Structs

AnyTx

Transaction with the information required to dispatch it to a service.

ArtifactId

The artifact identifier is required to construct service instances. In other words, an artifact identifier is similar to a class name, and a specific service instance is similar to a class instance.

ArtifactSpec

Exhaustive artifact specification. This information is enough to deploy an artifact.

ArtifactState

Current state of an artifact.

BlockchainData

Provides access to blockchain data for the executing service.

CallInfo

Information sufficient to route a transaction to a service.

CallSite

Site of a call where an ExecutionError may occur.

CallerAddress

Uniform presentation of a Caller.

DispatcherSchema

Schema of the dispatcher, used to store information about pending artifacts / service instances, and to reload artifacts / instances on node restart.

ErrorMatch

Matcher for ExecutionErrors that can have some fields unspecified. Can be compared to an ExceptionError, e.g., in tests. The unspecified fields will match any value in the error.

ExecutionContext

Provides the current state of the blockchain and the caller information for the call which is being executed.

ExecutionError

Result of unsuccessful runtime execution.

ExecutionStatus

Status of a call execution in a way it is stored in the blockchain. This result may be either an empty unit type, in case of success, or an ExecutionError, if execution has failed.

InstanceDescriptor

Instance descriptor contains information to access the running service instance.

InstanceSpec

Exhaustive service instance specification.

InstanceState

Current state of service instance in dispatcher.

Mailbox

Mailbox accumulating Actions to be performed by the dispatcher.

MigrationStatus

Result of execution of a migration script.

RuntimeInstance

Instance of Runtime with the corresponding ID.

Enums

ArtifactStatus

Status of an artifact deployment.

CallType

Type of a call to a service.

Caller

The authorization information for a service call.

CommonError

List of possible common errors.

CoreError

List of possible core errors.

DispatcherAction

Action to be performed by the dispatcher.

ErrorKind

Kind of execution error, divided into several distinct sub-groups.

InstanceQuery

Allows to query a service instance by either of the two identifiers.

InstanceStatus

Status of a service instance.

RuntimeFeature

Optional features that may or may not be supported by a particular Runtime.

RuntimeIdentifier

List of predefined runtimes.

Constants

SUPERVISOR_INSTANCE_ID

Persistent identifier of a supervisor service instance.

Traits

ExecutionFail

Trait representing an error type defined in the service or runtime code.

Runtime

Runtime environment for Exonum services.

SnapshotExt

Extension trait for Snapshot allowing to access blockchain data in a more structured way.

WellKnownRuntime

A subset of Runtimes with a well-known runtime identifier.

Functions

catch_panic

Invokes closure, capturing the cause of the unwinding panic if one occurs.

Type Definitions

InstanceId

Unique service instance identifier.

MethodId

Identifier of the method in the service interface required for the call.