[][src]Crate exonum_time

The time oracle service for Exonum.

Time service is designed to be a trusted source of actual time for the Exonum blockchain services. With this service, user services are able to access the calendar time supplied by validator nodes to the blockchain.

Basics of the Approach

Each validator at a specific time sends a transaction indicating its local time (usually immediately after the commit of each block). The time service maintains an index with the most current time values indicated separately by each validator. This index is updated after each transaction from any of the validators. A 1/3 quantile of these values (ordered by decreasing time) is then picked out from the index; this quantile is considered the actual time and is applied to determine the exact service time.

See the Exonum documentation for a high-level overview of the service, in particular, its design rationale and the proof of correctness.

HTTP API

REST API of the service is documented in the api module.

Examples

Use with TestKit

use chrono::{TimeZone, Utc};
use exonum::{
    helpers::Height,
    runtime::{InstanceId, SnapshotExt},
};
use exonum_rust_runtime::ServiceFactory;
use exonum_testkit::{Spec, TestKit, TestKitBuilder};
use exonum_time::{MockTimeProvider, TimeProvider, TimeSchema, TimeServiceFactory};

use std::sync::Arc;

const TIME_SERVICE_ID: InstanceId = 100;
const TIME_SERVICE_NAME: &'static str = "time-oracle";

// Time provider for a time service is chosen at the compile time.
// Here we use `MockTimeProvider` to get controllable results.
// In real world it makes sense to use `SystemTimeProvider` or your
// own implementation of `TimeProvider`.
let time_provider = Arc::new(MockTimeProvider::default());

// Factory for time service will create instances of the service with given
// time provider.
let time_service =
    TimeServiceFactory::with_provider(time_provider.clone() as Arc<dyn TimeProvider>);
let time_service = Spec::new(time_service).with_instance(TIME_SERVICE_ID, TIME_SERVICE_NAME, ());

// Create testkit with the time service.
let mut testkit: TestKit = TestKitBuilder::validator()
    .with(time_service)
    // Add other services here
    .build();

// Set time in `MockTimeProvider`.
time_provider.set_time(Utc.timestamp(10, 0));
// Create some blocks for time to appear in the blockchain.
testkit.create_blocks_until(Height(2));

// Obtain time service schema.
let snapshot = testkit.snapshot();
let time_schema: TimeSchema<_> = snapshot.service_schema(TIME_SERVICE_NAME).unwrap();
// Obtain time from the schema. Service can base its logic on this time.
let time = time_schema.time.get();
// With `MockServiceProvider` we can ensure that time is based on data
// provided by `TimeProvider`.
assert_eq!(time, Some(time_provider.time()));

Interaction with other service

Example of interaction with the time service can be found at GitHub.

Re-exports

pub use crate::api::ValidatorTime;

Modules

api

HTTP API for the time service. All APIs are accessible from the public HTTP server of the node.

Structs

MockTimeProvider

Mock time provider for service testing.

SystemTimeProvider

Provider of system time.

TimeSchema

Database schema of the time service. The schema is fully public.

TimeService

Time oracle service.

TimeServiceFactory

Time oracle service factory.

TxTime

Transaction that is sent by the validator after the commit of the block.

Enums

Error

Common errors emitted by transactions during execution.

Traits

TimeOracleInterface

Time oracle service transaction.

TimeOracleInterfaceMut

Time oracle service transaction.

TimeProvider

A helper trait that provides the node with a current time.