Trait exonum::blockchain::Service
[−]
[src]
pub trait Service: Send + Sync + 'static { fn service_id(&self) -> u16; fn service_name(&self) -> &str; fn state_hash(&self, snapshot: &Snapshot) -> Vec<Hash>; fn tx_from_raw(
&self,
raw: RawTransaction
) -> Result<Box<Transaction>, MessageError>; fn initialize(&self, fork: &mut Fork) -> Value { ... } fn handle_commit(&self, context: &ServiceContext) { ... } fn public_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> { ... } fn private_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> { ... } }
A trait that describes business logic of a concrete service.
See also the documentation page on services.
Examples
The following example provides a bare-bones foundation for implementing a service.
#[macro_use] extern crate exonum; // Exports from `exonum` crate skipped use exonum::encoding::Error as EncError; // Reused constants const SERVICE_ID: u16 = 8000; // Service schema struct MyServiceSchema<T> { view: T, } impl<T: AsRef<Snapshot>> MyServiceSchema<T> { fn new(view: T) -> Self { MyServiceSchema { view } } fn state_hash(&self) -> Vec<Hash> { // Calculates the state hash of the service } // Other read-only methods } impl<'a> MyServiceSchema<&'a mut Fork> { // Additional read-write methods } // Transaction definitions transactions! { MyTransactions { const SERVICE_ID = SERVICE_ID; struct TxA { // Transaction fields } struct TxB { // ... } } } impl Transaction for TxA { // Business logic implementation } impl Transaction for TxB { } // Service struct MyService {} impl Service for MyService { fn service_id(&self) -> u16 { SERVICE_ID } fn service_name(&self) -> &'static str { "my_special_unique_service" } fn state_hash(&self, snapshot: &Snapshot) -> Vec<Hash> { MyServiceSchema::new(snapshot).state_hash() } fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, EncError> { let tx = MyTransactions::tx_from_raw(raw)?; Ok(tx.into()) } }
Required Methods
fn service_id(&self) -> u16
Service identifier for database schema and service messages. Must be unique within the blockchain.
fn service_name(&self) -> &str
A comprehensive string service name. Must be unique within the blockchain.
fn state_hash(&self, snapshot: &Snapshot) -> Vec<Hash>
Returns a list of root hashes of tables that determine the current state
of the service database. These hashes are collected from all the services in a common
ProofMapIndex
accessible in the core schema as state_hash_aggregator
.
An empty vector can be returned if the service does not influence the blockchain state.
See also service_table_unique_key
.
fn tx_from_raw(
&self,
raw: RawTransaction
) -> Result<Box<Transaction>, MessageError>
&self,
raw: RawTransaction
) -> Result<Box<Transaction>, MessageError>
Tries to create a Transaction
from the given raw message.
Exonum framework only guarantees that SERVICE_ID
of the message is equal to the
identifier of this service, therefore the implementation should be ready to handle invalid
transactions that may come from byzantine nodes.
Service should return an error in the following cases (see MessageError
for more details):
- Incorrect transaction identifier.
- Incorrect data layout.
Service shouldn't perform signature check or logical validation of the transaction: these
operations should be performed in the Transaction::verify
and Transaction::execute
methods.
transactions!
macro generates code that allows simple implementation, see
the Service
example above.
Provided Methods
fn initialize(&self, fork: &mut Fork) -> Value
Initializes the information schema of the service and generates an initial service configuration. Called on genesis block creation.
fn handle_commit(&self, context: &ServiceContext)
Handles block commit. This handler is invoked for each service after commit of the block. For example, a service can create one or more transactions if a specific condition has occurred.
Try not to perform long operations in this handler.
fn public_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>>
Returns an API handler for public requests. The handler is mounted on
the /api/services/{service_name}
path at the public listen address
of all full nodes in the blockchain network.
fn private_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>>
Returns an API handler for private requests. The handler is mounted on
the /api/services/{service_name}
path at the private listen address
of all full nodes in the blockchain network.