extern crate time;
pub mod merkletree;
pub mod types;
pub mod constants;
use self::types::{
AttribOperation,
GetAttribOperation,
GetNymOperation,
GetSchemaOperationData,
GetSchemaOperation,
NymOperation,
Request,
SchemaOperation,
SchemaOperationData,
ClaimDefOperation,
ClaimDefOperationData,
GetClaimDefOperation,
GetDdoOperation,
NodeOperation,
NodeOperationData,
Role,
GetTxnOperation
};
use errors::common::CommonError;
use utils::json::{JsonEncodable, JsonDecodable};
use utils::crypto::base58::Base58;
trait LedgerSerializer {
fn serialize(&self) -> String;
}
pub struct LedgerService {}
impl LedgerService {
pub fn new() -> LedgerService {
LedgerService {}
}
pub fn build_nym_request(&self, identifier: &str, dest: &str, verkey: Option<&str>,
alias: Option<&str>, role: Option<&str>) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let role = match role {
Some(r) =>
match r.clone() {
"STEWARD" => Some(Role::STEWARD as i32),
"TRUSTEE" => Some(Role::TRUSTEE as i32),
role @ _ => return Err(CommonError::InvalidStructure(format!("Invalid role: {}", role)))
},
_ => None
};
let operation = NymOperation::new(dest.to_string(),
verkey.as_ref().map(|s| s.to_string()),
alias.as_ref().map(|s| s.to_string()),
role.as_ref().map(|s| s.to_string()));
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid nym request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_nym_request(&self, identifier: &str, dest: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let operation = GetNymOperation::new(dest.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get_nym request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_ddo_request(&self, identifier: &str, dest: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let operation = GetDdoOperation::new(dest.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get_ddo request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_attrib_request(&self, identifier: &str, dest: &str, hash: Option<&str>,
raw: Option<&str>, enc: Option<&str>) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
if raw.is_none() && hash.is_none() && enc.is_none() {
return Err(CommonError::InvalidStructure(format!("Either raw or hash or enc must be specified")))
}
let req_id = LedgerService::get_req_id();
let operation = AttribOperation::new(dest.to_string(),
hash.as_ref().map(|s| s.to_string()),
raw.as_ref().map(|s| s.to_string()),
enc.as_ref().map(|s| s.to_string()));
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid attrib request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_attrib_request(&self, identifier: &str, dest: &str, raw: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let operation = GetAttribOperation::new(dest.to_string(),
raw.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get_attrib request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_schema_request(&self, identifier: &str, data: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
let req_id = LedgerService::get_req_id();
SchemaOperationData::from_json(&data)
.map_err(|err| CommonError::InvalidStructure(format!("Invalid data json: {}", err.to_string())))?;
let operation = SchemaOperation::new(data.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid schema request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_schema_request(&self, identifier: &str, dest: &str, data: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let data = GetSchemaOperationData::from_json(data)
.map_err(|err| CommonError::InvalidStructure(format!("Invalid data json: {}", err.to_string())))?;
let operation = GetSchemaOperation::new(dest.to_string(), data);
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get_schema request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_claim_def_request(&self, identifier: &str, _ref: i32, signature_type: &str, data: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
let req_id = LedgerService::get_req_id();
ClaimDefOperationData::from_json(&data)
.map_err(|err| CommonError::InvalidStructure(format!("Invalid data json: {}", err.to_string())))?;
let operation = ClaimDefOperation::new(_ref, signature_type.to_string(), data.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid claim_def request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_claim_def_request(&self, identifier: &str, _ref: i32, signature_type: &str, origin: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&origin)?;
let req_id = LedgerService::get_req_id();
let operation = GetClaimDefOperation::new(_ref,
signature_type.to_string(),
origin.to_string());
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get_claim_def request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_node_request(&self, identifier: &str, dest: &str, data: &str) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
Base58::decode(&dest)?;
let req_id = LedgerService::get_req_id();
let data = NodeOperationData::from_json(&data)
.map_err(|err| CommonError::InvalidStructure(format!("Invalid data json: {}", err.to_string())))?;
let operation = NodeOperation::new(dest.to_string(), data);
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid node request json: {}", err.to_string())))?;
Ok(request_json)
}
pub fn build_get_txn_request(&self, identifier: &str, data: i32) -> Result<String, CommonError> {
Base58::decode(&identifier)?;
let req_id = LedgerService::get_req_id();
let operation = GetTxnOperation::new(data);
let request = Request::new(req_id,
identifier.to_string(),
operation);
let request_json = Request::to_json(&request)
.map_err(|err| CommonError::InvalidState(format!("Invalid get txn request json: {}", err.to_string())))?;
Ok(request_json)
}
fn get_req_id() -> u64 {
time::get_time().sec as u64 * (1e9 as u64) + time::get_time().nsec as u64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn build_nym_request_works_for_only_required_fields() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let expected_result = r#""identifier":"identifier","operation":{"type":"1","dest":"dest"}"#;
let nym_request = ledger_service.build_nym_request(identifier, dest, None, None, None);
assert!(nym_request.is_ok());
let nym_request = nym_request.unwrap();
assert!(nym_request.contains(expected_result));
}
#[test]
fn build_nym_request_works_for_optional_fields() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let verkey = "verkey";
let alias = "some_alias";
let expected_result = r#""identifier":"identifier","operation":{"type":"1","dest":"dest","verkey":"verkey","alias":"some_alias"}"#;
let nym_request = ledger_service.build_nym_request(identifier, dest, Some(verkey), Some(alias), None);
assert!(nym_request.is_ok());
let nym_request = nym_request.unwrap();
assert!(nym_request.contains(expected_result));
}
#[test]
fn build_get_nym_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let expected_result = r#""identifier":"identifier","operation":{"type":"105","dest":"dest"}"#;
let get_nym_request = ledger_service.build_get_nym_request(identifier, dest);
assert!(get_nym_request.is_ok());
let get_nym_request = get_nym_request.unwrap();
assert!(get_nym_request.contains(expected_result));
}
#[test]
fn build_get_ddo_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let expected_result = r#""identifier":"identifier","operation":{"type":"120","dest":"dest"}"#;
let get_ddo_request = ledger_service.build_get_ddo_request(identifier, dest);
assert!(get_ddo_request.is_ok());
let get_ddo_request = get_ddo_request.unwrap();
assert!(get_ddo_request.contains(expected_result));
}
#[test]
fn build_attrib_request_works_for_miss_attrib_field() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let attrib_request = ledger_service.build_attrib_request(identifier, dest, None, None, None);
assert!(attrib_request.is_err());
}
#[test]
fn build_attrib_request_works_for_hash_field() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let hash = "hash";
let expected_result = r#""identifier":"identifier","operation":{"type":"100","dest":"dest","hash":"hash"}"#;
let attrib_request = ledger_service.build_attrib_request(identifier, dest, Some(hash), None, None);
assert!(attrib_request.is_ok());
let attrib_request = attrib_request.unwrap();
assert!(attrib_request.contains(expected_result));
}
#[test]
fn build_get_attrib_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let raw = "raw";
let expected_result = r#""identifier":"identifier","operation":{"type":"104","dest":"dest","raw":"raw"}"#;
let get_attrib_request = ledger_service.build_get_attrib_request(identifier, dest, raw);
assert!(get_attrib_request.is_ok());
let get_attrib_request = get_attrib_request.unwrap();
assert!(get_attrib_request.contains(expected_result));
}
#[test]
fn build_schema_request_works_for_wrong_data() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let data = r#"{"name":"name"}"#;
let get_attrib_request = ledger_service.build_schema_request(identifier, data);
assert!(get_attrib_request.is_err());
}
#[test]
fn build_schema_request_works_for_correct_data() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let data = r#"{"name":"name", "version":"1.0", "keys":["name","male"]}"#;
let expected_result = r#""operation":{"type":"101","data":"{\"name\":\"name\", \"version\":\"1.0\", \"keys\":[\"name\",\"male\"]"#;
let schema_request = ledger_service.build_schema_request(identifier, data);
assert!(schema_request.is_ok());
let schema_request = schema_request.unwrap();
assert!(schema_request.contains(expected_result));
}
#[test]
fn build_get_schema_request_works_for_wrong_data() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let data = r#"{"name":"name","keys":["name","male"]}"#;
let get_schema_request = ledger_service.build_get_schema_request(identifier, identifier, data);
assert!(get_schema_request.is_err());
}
#[test]
fn build_get_schema_request_works_for_correct_data() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let data = r#"{"name":"name","version":"1.0"}"#;
let expected_result = r#""identifier":"identifier","operation":{"type":"107","dest":"identifier","data":{"name":"name","version":"1.0"}}"#;
let get_schema_request = ledger_service.build_get_schema_request(identifier, identifier, data);
assert!(get_schema_request.is_ok());
let get_schema_request = get_schema_request.unwrap();
assert!(get_schema_request.contains(expected_result));
}
#[test]
fn build_get_claim_def_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let _ref = 1;
let signature_type = "signature_type";
let origin = "origin";
let expected_result = r#""identifier":"identifier","operation":{"type":"108","ref":1,"signature_type":"signature_type","origin":"origin"}"#;
let get_claim_def_request = ledger_service.build_get_claim_def_request(identifier, _ref, signature_type, origin);
assert!(get_claim_def_request.is_ok());
let get_claim_def_request = get_claim_def_request.unwrap();
assert!(get_claim_def_request.contains(expected_result));
}
#[test]
fn build_node_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let data = r#"{"node_ip":"ip", "node_port": 1, "client_ip": "ip", "client_port": 1, "alias":"some", "services": ["VALIDATOR"]}"#;
let expected_result = r#""identifier":"identifier","operation":{"type":"0","dest":"dest","data":{"node_ip":"ip","node_port":1,"client_ip":"ip","client_port":1,"alias":"some","services":["VALIDATOR"]}}"#;
let node_request = ledger_service.build_node_request(identifier, dest, data);
assert!(node_request.is_ok());
let node_request = node_request.unwrap();
assert!(node_request.contains(expected_result));
}
#[test]
fn build_node_request_works_for_wrong_data() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let dest = "dest";
let data = r#"{"node_ip":"ip", "node_port": 1, "client_ip": "ip", "client_port": 1}"#;
let node_request = ledger_service.build_node_request(identifier, dest, data);
assert!(node_request.is_err());
}
#[test]
fn build_get_txn_request_works() {
let ledger_service = LedgerService::new();
let identifier = "identifier";
let expected_result = r#""identifier":"identifier","operation":{"type":"106","data":1}"#;
let get_txn_request = ledger_service.build_get_txn_request(identifier, 1);
assert!(get_txn_request.is_ok());
let get_txn_request = get_txn_request.unwrap();
assert!(get_txn_request.contains(expected_result));
}
}