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

Service identifier for database schema and service messages. Must be unique within the blockchain.

A comprehensive string service name. Must be unique within the blockchain.

Important traits for Vec<u8>

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.

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

Initializes the information schema of the service and generates an initial service configuration. Called on genesis block creation.

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.

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.

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.

Implementors