1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright 2020 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! 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][docs:time] for a high-level overview of the
//! service, in particular, its design rationale and the proof of correctness.
//!
//! [docs:time]: https://exonum.com/doc/version/latest/advanced/time
//!
//! # HTTP API
//!
//! REST API of the service is documented in the [`api` module](api/index.html).
//!
//! # 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].
//!
//! [at GitHub]: https://github.com/exonum/exonum/blob/master/services/time/examples/simple_service/main.rs
use ;
use ;
use Arc;
pub use crate::;
/// Time oracle service.
/// Time oracle service factory.
///
/// By default, it creates time service instances with [`SystemTimeProvider`].
///
/// [`SystemTimeProvider`]: struct.SystemTimeProvider.html