github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/processor/src/handler.rs (about)

     1  // Copyright 2018 Cargill Incorporated
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  use protobuf;
    16  use protobuf::Message;
    17  use protobuf::RepeatedField;
    18  
    19  use std::collections::HashMap;
    20  
    21  use sawtooth_sdk::processor::handler::ApplyError;
    22  use sawtooth_sdk::processor::handler::TransactionContext;
    23  use sawtooth_sdk::processor::handler::TransactionHandler;
    24  use sawtooth_sdk::messages::processor::TpProcessRequest;
    25  
    26  use messages::*;
    27  use addressing::*;
    28  
    29  const PROPERTY_PAGE_MAX_LENGTH: usize = 256;
    30  
    31  #[derive(Debug, Clone)]
    32  enum Action {
    33      CreateAgent(payload::CreateAgentAction),
    34      CreateRecord(payload::CreateRecordAction),
    35      FinalizeRecord(payload::FinalizeRecordAction),
    36      CreateRecordType(payload::CreateRecordTypeAction),
    37      UpdateProperties(payload::UpdatePropertiesAction),
    38      CreateProposal(payload::CreateProposalAction),
    39      AnswerProposal(payload::AnswerProposalAction),
    40      RevokeReporter(payload::RevokeReporterAction),
    41  }
    42  
    43  struct SupplyChainPayload {
    44      action: Action,
    45      timestamp: u64,
    46  }
    47  
    48  impl SupplyChainPayload {
    49      pub fn new(payload: &[u8]) -> Result<Option<SupplyChainPayload>, ApplyError> {
    50          let payload: payload::SCPayload = match protobuf::parse_from_bytes(payload) {
    51              Ok(payload) => payload,
    52              Err(_) => {
    53                  return Err(ApplyError::InvalidTransaction(String::from(
    54                      "Cannot deserialize payload",
    55                  )))
    56              }
    57          };
    58  
    59          let supply_chain_action = payload.get_action();
    60          let action = match supply_chain_action {
    61              payload::SCPayload_Action::CREATE_AGENT => {
    62                  let create_agent = payload.get_create_agent();
    63                  if create_agent.get_name() == "" {
    64                      return Err(ApplyError::InvalidTransaction(String::from(
    65                          "Agent name cannot be an empty string",
    66                      )));
    67                  }
    68                  Action::CreateAgent(create_agent.clone())
    69              }
    70              payload::SCPayload_Action::CREATE_RECORD => {
    71                  let create_record = payload.get_create_record();
    72                  if create_record.get_record_id() == "" {
    73                      return Err(ApplyError::InvalidTransaction(String::from(
    74                          "Record id cannot be empty string",
    75                      )));
    76                  }
    77                  Action::CreateRecord(create_record.clone())
    78              }
    79              payload::SCPayload_Action::FINALIZE_RECORD => {
    80                  Action::FinalizeRecord(payload.get_finalize_record().clone())
    81              }
    82              payload::SCPayload_Action::CREATE_RECORD_TYPE => {
    83                  let create_record_type = payload.get_create_record_type();
    84                  if create_record_type.get_name() == "" {
    85                      return Err(ApplyError::InvalidTransaction(String::from(
    86                          "Record Type name cannot be an empty string",
    87                      )));
    88                  };
    89                  let properties = create_record_type.get_properties();
    90                  if properties.len() == 0 {
    91                      return Err(ApplyError::InvalidTransaction(String::from(
    92                          "Record type must have at least one property",
    93                      )));
    94                  }
    95                  for prop in properties {
    96                      if prop.name == "" {
    97                          return Err(ApplyError::InvalidTransaction(String::from(
    98                              "Property name cannot be an empty string",
    99                          )));
   100                      }
   101                  }
   102  
   103                  Action::CreateRecordType(create_record_type.clone())
   104              }
   105              payload::SCPayload_Action::UPDATE_PROPERTIES => {
   106                  Action::UpdateProperties(payload.get_update_properties().clone())
   107              }
   108              payload::SCPayload_Action::CREATE_PROPOSAL => {
   109                  Action::CreateProposal(payload.get_create_proposal().clone())
   110              }
   111              payload::SCPayload_Action::ANSWER_PROPOSAL => {
   112                  Action::AnswerProposal(payload.get_answer_proposal().clone())
   113              }
   114              payload::SCPayload_Action::REVOKE_REPORTER => {
   115                  Action::RevokeReporter(payload.get_revoke_reporter().clone())
   116              }
   117          };
   118          let timestamp = match payload.get_timestamp() {
   119              0 => {
   120                  return Err(ApplyError::InvalidTransaction(String::from(
   121                      "Timestamp is not set",
   122                  )))
   123              }
   124              x => x,
   125          };
   126  
   127          Ok(Some(SupplyChainPayload {
   128              action: action,
   129              timestamp: timestamp,
   130          }))
   131      }
   132  
   133      pub fn get_action(&self) -> Action {
   134          self.action.clone()
   135      }
   136  
   137      pub fn get_timestamp(&self) -> u64 {
   138          self.timestamp
   139      }
   140  }
   141  
   142  pub struct SupplyChainState<'a> {
   143      context: &'a mut TransactionContext,
   144  }
   145  
   146  impl<'a> SupplyChainState<'a> {
   147      pub fn new(context: &'a mut TransactionContext) -> SupplyChainState {
   148          SupplyChainState { context: context }
   149      }
   150  
   151      pub fn get_record(&mut self, record_id: &str) -> Result<Option<record::Record>, ApplyError> {
   152          let address = make_record_address(record_id);
   153          let d = self.context.get_state(vec![address])?;
   154          match d {
   155              Some(packed) => {
   156                  let records: record::RecordContainer =
   157                      match protobuf::parse_from_bytes(packed.as_slice()) {
   158                          Ok(records) => records,
   159                          Err(_) => {
   160                              return Err(ApplyError::InternalError(String::from(
   161                                  "Cannot deserialize record container",
   162                              )))
   163                          }
   164                      };
   165  
   166                  for record in records.get_entries() {
   167                      if record.record_id == record_id {
   168                          return Ok(Some(record.clone()));
   169                      }
   170                  }
   171                  Ok(None)
   172              }
   173              None => Ok(None),
   174          }
   175      }
   176  
   177      pub fn set_record(
   178          &mut self,
   179          record_id: &str,
   180          record: record::Record,
   181      ) -> Result<(), ApplyError> {
   182          let address = make_record_address(record_id);
   183          let d = self.context.get_state(vec![address.clone()])?;
   184          let mut record_container = match d {
   185              Some(packed) => match protobuf::parse_from_bytes(packed.as_slice()) {
   186                  Ok(records) => records,
   187                  Err(_) => {
   188                      return Err(ApplyError::InternalError(String::from(
   189                          "Cannot deserialize record container",
   190                      )))
   191                  }
   192              },
   193              None => record::RecordContainer::new(),
   194          };
   195          // remove old record if it exists and sort the records by record id
   196          let records = record_container.get_entries().to_vec();
   197          let mut index = None;
   198          let mut count = 0;
   199          for record in records.clone() {
   200              if record.record_id == record_id {
   201                  index = Some(count);
   202                  break;
   203              }
   204              count = count + 1;
   205          }
   206  
   207          match index {
   208              Some(x) => {
   209                  record_container.entries.remove(x);
   210              }
   211              None => (),
   212          };
   213          record_container.entries.push(record);
   214          record_container
   215              .entries
   216              .sort_by_key(|r| r.clone().record_id);
   217          let serialized = match record_container.write_to_bytes() {
   218              Ok(serialized) => serialized,
   219              Err(_) => {
   220                  return Err(ApplyError::InternalError(String::from(
   221                      "Cannot serialize record container",
   222                  )))
   223              }
   224          };
   225          let mut sets = HashMap::new();
   226          sets.insert(address, serialized);
   227          self.context
   228              .set_state(sets)
   229              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   230          Ok(())
   231      }
   232  
   233      pub fn get_record_type(
   234          &mut self,
   235          type_name: &str,
   236      ) -> Result<Option<record::RecordType>, ApplyError> {
   237          let address = make_record_type_address(type_name);
   238          let d = self.context.get_state(vec![address])?;
   239          match d {
   240              Some(packed) => {
   241                  let record_types: record::RecordTypeContainer =
   242                      match protobuf::parse_from_bytes(packed.as_slice()) {
   243                          Ok(record_types) => record_types,
   244                          Err(_) => {
   245                              return Err(ApplyError::InternalError(String::from(
   246                                  "Cannot deserialize record type container",
   247                              )))
   248                          }
   249                      };
   250  
   251                  for record_type in record_types.get_entries() {
   252                      if record_type.name == type_name {
   253                          return Ok(Some(record_type.clone()));
   254                      }
   255                  }
   256                  Ok(None)
   257              }
   258              None => Ok(None),
   259          }
   260      }
   261  
   262      pub fn set_record_type(
   263          &mut self,
   264          type_name: &str,
   265          record_type: record::RecordType,
   266      ) -> Result<(), ApplyError> {
   267          let address = make_record_type_address(type_name);
   268          let d = self.context.get_state(vec![address.clone()])?;
   269          let mut record_types = match d {
   270              Some(packed) => match protobuf::parse_from_bytes(packed.as_slice()) {
   271                  Ok(record_types) => record_types,
   272                  Err(_) => {
   273                      return Err(ApplyError::InternalError(String::from(
   274                          "Cannot deserialize record container",
   275                      )))
   276                  }
   277              },
   278              None => record::RecordTypeContainer::new(),
   279          };
   280  
   281          record_types.entries.push(record_type);
   282          record_types.entries.sort_by_key(|rt| rt.clone().name);
   283          let serialized = match record_types.write_to_bytes() {
   284              Ok(serialized) => serialized,
   285              Err(_) => {
   286                  return Err(ApplyError::InternalError(String::from(
   287                      "Cannot serialize record type container",
   288                  )))
   289              }
   290          };
   291          let mut sets = HashMap::new();
   292          sets.insert(address, serialized);
   293          self.context
   294              .set_state(sets)
   295              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   296          Ok(())
   297      }
   298  
   299      pub fn get_agent(&mut self, agent_id: &str) -> Result<Option<agent::Agent>, ApplyError> {
   300          let address = make_agent_address(agent_id);
   301          let d = self.context.get_state(vec![address])?;
   302          match d {
   303              Some(packed) => {
   304                  let agents: agent::AgentContainer =
   305                      match protobuf::parse_from_bytes(packed.as_slice()) {
   306                          Ok(agents) => agents,
   307                          Err(_) => {
   308                              return Err(ApplyError::InternalError(String::from(
   309                                  "Cannot deserialize agent container",
   310                              )))
   311                          }
   312                      };
   313  
   314                  for agent in agents.get_entries() {
   315                      if agent.public_key == agent_id {
   316                          return Ok(Some(agent.clone()));
   317                      }
   318                  }
   319                  Ok(None)
   320              }
   321              None => Ok(None),
   322          }
   323      }
   324  
   325      pub fn set_agent(&mut self, agent_id: &str, agent: agent::Agent) -> Result<(), ApplyError> {
   326          let address = make_agent_address(agent_id);
   327          let d = self.context.get_state(vec![address.clone()])?;
   328          let mut agents = match d {
   329              Some(packed) => match protobuf::parse_from_bytes(packed.as_slice()) {
   330                  Ok(agents) => agents,
   331                  Err(_) => {
   332                      return Err(ApplyError::InternalError(String::from(
   333                          "Cannot deserialize agent container",
   334                      )))
   335                  }
   336              },
   337              None => agent::AgentContainer::new(),
   338          };
   339  
   340          agents.entries.push(agent);
   341          agents.entries.sort_by_key(|a| a.clone().public_key);
   342          let serialized = match agents.write_to_bytes() {
   343              Ok(serialized) => serialized,
   344              Err(_) => {
   345                  return Err(ApplyError::InternalError(String::from(
   346                      "Cannot serialize agent container",
   347                  )))
   348              }
   349          };
   350          let mut sets = HashMap::new();
   351          sets.insert(address, serialized);
   352          self.context
   353              .set_state(sets)
   354              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   355          Ok(())
   356      }
   357  
   358      pub fn get_property(
   359          &mut self,
   360          record_id: &str,
   361          property_name: &str,
   362      ) -> Result<Option<property::Property>, ApplyError> {
   363          let address = make_property_address(record_id, property_name, 0);
   364          let d = self.context.get_state(vec![address])?;
   365          match d {
   366              Some(packed) => {
   367                  let properties: property::PropertyContainer =
   368                      match protobuf::parse_from_bytes(packed.as_slice()) {
   369                          Ok(properties) => properties,
   370                          Err(_) => {
   371                              return Err(ApplyError::InternalError(String::from(
   372                                  "Cannot deserialize property container",
   373                              )))
   374                          }
   375                      };
   376  
   377                  for property in properties.get_entries() {
   378                      if property.name == property_name {
   379                          return Ok(Some(property.clone()));
   380                      }
   381                  }
   382                  Ok(None)
   383              }
   384              None => Ok(None),
   385          }
   386      }
   387  
   388      pub fn set_property(
   389          &mut self,
   390          record_id: &str,
   391          property_name: &str,
   392          property: property::Property,
   393      ) -> Result<(), ApplyError> {
   394          let address = make_property_address(record_id, property_name, 0);
   395          let d = self.context.get_state(vec![address.clone()])?;
   396          let mut property_container = match d {
   397              Some(packed) => match protobuf::parse_from_bytes(packed.as_slice()) {
   398                  Ok(properties) => properties,
   399                  Err(_) => {
   400                      return Err(ApplyError::InternalError(String::from(
   401                          "Cannot deserialize property container",
   402                      )))
   403                  }
   404              },
   405              None => property::PropertyContainer::new(),
   406          };
   407          // remove old property if it exists and sort the properties by name
   408          let properties = property_container.get_entries().to_vec();
   409          let mut index = None;
   410          let mut count = 0;
   411          for prop in properties.clone() {
   412              if prop.name == property_name {
   413                  index = Some(count);
   414                  break;
   415              }
   416              count = count + 1;
   417          }
   418  
   419          match index {
   420              Some(x) => {
   421                  property_container.entries.remove(x);
   422              }
   423              None => (),
   424          };
   425          property_container.entries.push(property);
   426          property_container.entries.sort_by_key(|p| p.clone().name);
   427          let serialized = match property_container.write_to_bytes() {
   428              Ok(serialized) => serialized,
   429              Err(_) => {
   430                  return Err(ApplyError::InternalError(String::from(
   431                      "Cannot serialize property container",
   432                  )))
   433              }
   434          };
   435          let mut sets = HashMap::new();
   436          sets.insert(address, serialized);
   437          self.context
   438              .set_state(sets)
   439              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   440          Ok(())
   441      }
   442  
   443      pub fn get_property_page(
   444          &mut self,
   445          record_id: &str,
   446          property_name: &str,
   447          page: u32,
   448      ) -> Result<Option<property::PropertyPage>, ApplyError> {
   449          let address = make_property_address(record_id, property_name, page);
   450          let d = self.context.get_state(vec![address])?;
   451          match d {
   452              Some(packed) => {
   453                  let property_pages: property::PropertyPageContainer =
   454                      match protobuf::parse_from_bytes(packed.as_slice()) {
   455                          Ok(property_pages) => property_pages,
   456                          Err(_) => {
   457                              return Err(ApplyError::InternalError(String::from(
   458                                  "Cannot deserialize property page container",
   459                              )))
   460                          }
   461                      };
   462  
   463                  for property_page in property_pages.get_entries() {
   464                      if property_page.name == property_name {
   465                          return Ok(Some(property_page.clone()));
   466                      }
   467                  }
   468                  Ok(None)
   469              }
   470              None => Ok(None),
   471          }
   472      }
   473  
   474      pub fn set_property_page(
   475          &mut self,
   476          record_id: &str,
   477          property_name: &str,
   478          page_num: u32,
   479          property_page: property::PropertyPage,
   480      ) -> Result<(), ApplyError> {
   481          let address = make_property_address(record_id, property_name, page_num);
   482          let d = self.context.get_state(vec![address.clone()])?;
   483          let mut property_pages = match d {
   484              Some(packed) => match protobuf::parse_from_bytes(packed.as_slice()) {
   485                  Ok(property_pages) => property_pages,
   486                  Err(_) => {
   487                      return Err(ApplyError::InternalError(String::from(
   488                          "Cannot deserialize property page container",
   489                      )))
   490                  }
   491              },
   492              None => property::PropertyPageContainer::new(),
   493          };
   494          // remove old property page if it exists and sort the property pages by name
   495          let pages = property_pages.get_entries().to_vec();
   496          let mut index = None;
   497          let mut count = 0;
   498          for page in pages.clone() {
   499              if page.name == property_name {
   500                  index = Some(count);
   501                  break;
   502              }
   503              count = count + 1;
   504          }
   505  
   506          match index {
   507              Some(x) => {
   508                  property_pages.entries.remove(x);
   509              }
   510              None => (),
   511          };
   512          property_pages.entries.push(property_page);
   513          property_pages.entries.sort_by_key(|pp| pp.clone().name);
   514          let serialized = match property_pages.write_to_bytes() {
   515              Ok(serialized) => serialized,
   516              Err(_) => {
   517                  return Err(ApplyError::InternalError(String::from(
   518                      "Cannot serialize property page container",
   519                  )))
   520              }
   521          };
   522          let mut sets = HashMap::new();
   523          sets.insert(address, serialized);
   524          self.context
   525              .set_state(sets)
   526              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   527          Ok(())
   528      }
   529  
   530      pub fn get_proposal_container(
   531          &mut self,
   532          record_id: &str,
   533          agent_id: &str,
   534      ) -> Result<Option<proposal::ProposalContainer>, ApplyError> {
   535          let address = make_proposal_address(record_id, agent_id);
   536          let d = self.context.get_state(vec![address])?;
   537          match d {
   538              Some(packed) => {
   539                  let proposals: proposal::ProposalContainer =
   540                      match protobuf::parse_from_bytes(packed.as_slice()) {
   541                          Ok(property_pages) => property_pages,
   542                          Err(_) => {
   543                              return Err(ApplyError::InternalError(String::from(
   544                                  "Cannot deserialize proposal container",
   545                              )))
   546                          }
   547                      };
   548  
   549                  Ok(Some(proposals))
   550              }
   551              None => Ok(None),
   552          }
   553      }
   554  
   555      pub fn set_proposal_container(
   556          &mut self,
   557          record_id: &str,
   558          agent_id: &str,
   559          proposals: proposal::ProposalContainer,
   560      ) -> Result<(), ApplyError> {
   561          let address = make_proposal_address(record_id, agent_id);
   562          let serialized = match proposals.write_to_bytes() {
   563              Ok(serialized) => serialized,
   564              Err(_) => {
   565                  return Err(ApplyError::InternalError(String::from(
   566                      "Cannot serialize proposal container",
   567                  )))
   568              }
   569          };
   570          let mut sets = HashMap::new();
   571          sets.insert(address, serialized);
   572          self.context
   573              .set_state(sets)
   574              .map_err(|err| ApplyError::InternalError(format!("{}", err)))?;
   575          Ok(())
   576      }
   577  }
   578  
   579  pub struct SupplyChainTransactionHandler {
   580      family_name: String,
   581      family_versions: Vec<String>,
   582      namespaces: Vec<String>,
   583  }
   584  
   585  impl SupplyChainTransactionHandler {
   586      pub fn new() -> SupplyChainTransactionHandler {
   587          SupplyChainTransactionHandler {
   588              family_name: "supply_chain".to_string(),
   589              family_versions: vec!["1.1".to_string()],
   590              namespaces: vec![get_supply_chain_prefix().to_string()],
   591          }
   592      }
   593  
   594      fn _create_agent(
   595          &self,
   596          payload: payload::CreateAgentAction,
   597          mut state: SupplyChainState,
   598          signer: &str,
   599          timestamp: u64,
   600      ) -> Result<(), ApplyError> {
   601          let name = payload.get_name();
   602          match state.get_agent(signer) {
   603              Ok(Some(_)) => {
   604                  return Err(ApplyError::InvalidTransaction(format!(
   605                      "Agent already exists: {}",
   606                      name
   607                  )))
   608              }
   609              Ok(None) => (),
   610              Err(err) => return Err(err),
   611          }
   612  
   613          let mut new_agent = agent::Agent::new();
   614          new_agent.set_public_key(signer.to_string());
   615          new_agent.set_name(name.to_string());
   616          new_agent.set_timestamp(timestamp);
   617  
   618          state.set_agent(signer, new_agent)?;
   619          Ok(())
   620      }
   621  
   622      fn _create_record(
   623          &self,
   624          payload: payload::CreateRecordAction,
   625          mut state: SupplyChainState,
   626          signer: &str,
   627          timestamp: u64,
   628      ) -> Result<(), ApplyError> {
   629          match state.get_agent(signer) {
   630              Ok(Some(_)) => (),
   631              Ok(None) => {
   632                  return Err(ApplyError::InvalidTransaction(format!(
   633                      "Agent is not register: {}",
   634                      signer
   635                  )))
   636              }
   637              Err(err) => return Err(err),
   638          }
   639          let record_id = payload.get_record_id();
   640          match state.get_record(record_id) {
   641              Ok(Some(_)) => {
   642                  return Err(ApplyError::InvalidTransaction(format!(
   643                      "Record already exists: {}",
   644                      record_id
   645                  )))
   646              }
   647              Ok(None) => (),
   648              Err(err) => return Err(err),
   649          }
   650  
   651          let type_name = payload.get_record_type();
   652          let record_type = match state.get_record_type(type_name) {
   653              Ok(Some(record_type)) => record_type,
   654              Ok(None) => {
   655                  return Err(ApplyError::InvalidTransaction(format!(
   656                      "Record Type does not exist {}",
   657                      type_name
   658                  )))
   659              }
   660              Err(err) => return Err(err),
   661          };
   662  
   663          let mut type_schemata: HashMap<&str, property::PropertySchema> = HashMap::new();
   664          let mut required_properties: HashMap<&str, property::PropertySchema> = HashMap::new();
   665          let mut provided_properties: HashMap<&str, property::PropertyValue> = HashMap::new();
   666          for property in record_type.get_properties() {
   667              type_schemata.insert(property.get_name(), property.clone());
   668              if property.get_required() {
   669                  required_properties.insert(property.get_name(), property.clone());
   670              }
   671          }
   672  
   673          for property in payload.get_properties() {
   674              provided_properties.insert(property.get_name(), property.clone());
   675          }
   676  
   677          for name in required_properties.keys() {
   678              if !provided_properties.contains_key(name) {
   679                  return Err(ApplyError::InvalidTransaction(format!(
   680                      "Required property {} not provided",
   681                      name
   682                  )));
   683              }
   684          }
   685  
   686          for (provided_name, provided_properties) in provided_properties.clone() {
   687              let required_type = match type_schemata.get(provided_name) {
   688                  Some(required_type) => required_type.data_type,
   689                  None => {
   690                      return Err(ApplyError::InvalidTransaction(format!(
   691                          "Provided property {} is not in schemata",
   692                          provided_name
   693                      )))
   694                  }
   695              };
   696              let provided_type = provided_properties.data_type;
   697              if provided_type != required_type {
   698                  return Err(ApplyError::InvalidTransaction(format!(
   699                      "Value provided for {} is the wrong type",
   700                      provided_name
   701                  )));
   702              };
   703  
   704              let is_delayed = match type_schemata.get(provided_name) {
   705                  Some(property_schema) => property_schema.delayed,
   706                  None => false,
   707              };
   708              if is_delayed {
   709                  return Err(ApplyError::InvalidTransaction(format!(
   710                      "Property is 'delayed', and cannot be set at record creation: {}",
   711                      provided_name
   712                  )));
   713              };
   714          }
   715          let mut new_record = record::Record::new();
   716          new_record.set_record_id(record_id.to_string());
   717          new_record.set_record_type(type_name.to_string());
   718          new_record.set_field_final(false);
   719  
   720          let mut owner = record::Record_AssociatedAgent::new();
   721          owner.set_agent_id(signer.to_string());
   722          owner.set_timestamp(timestamp);
   723          new_record.owners.push(owner.clone());
   724          new_record.custodians.push(owner.clone());
   725  
   726          state.set_record(record_id, new_record)?;
   727  
   728          let mut reporter = property::Property_Reporter::new();
   729          reporter.set_public_key(signer.to_string());
   730          reporter.set_authorized(true);
   731          reporter.set_index(0);
   732  
   733          for (property_name, property) in type_schemata {
   734              let mut new_property = property::Property::new();
   735              new_property.set_name(property_name.to_string());
   736              new_property.set_record_id(record_id.to_string());
   737              new_property.set_data_type(property.get_data_type());
   738              new_property.reporters.push(reporter.clone());
   739              new_property.set_current_page(1);
   740              new_property.set_wrapped(false);
   741              new_property.set_fixed(property.get_fixed());
   742              new_property.set_number_exponent(property.get_number_exponent());
   743              new_property.set_enum_options(
   744                  RepeatedField::from_vec(property.get_enum_options().to_vec()));
   745              new_property.set_struct_properties(
   746                  RepeatedField::from_vec(property.get_struct_properties().to_vec()));
   747              new_property.set_unit(property.get_unit().to_string());
   748  
   749              state.set_property(record_id, property_name, new_property.clone())?;
   750  
   751              let mut new_property_page = property::PropertyPage::new();
   752              new_property_page.set_name(property_name.to_string());
   753              new_property_page.set_record_id(record_id.to_string());
   754  
   755              if provided_properties.contains_key(property_name) {
   756                  let provided_property = &provided_properties[property_name];
   757                  let reported_value = match self._make_new_reported_value(
   758                      0,
   759                      timestamp,
   760                      provided_property,
   761                      &new_property,
   762                  ) {
   763                      Ok(reported_value) => reported_value,
   764                      Err(err) => return Err(err),
   765                  };
   766  
   767                  new_property_page.reported_values.push(reported_value);
   768              }
   769              state.set_property_page(record_id, property_name, 1, new_property_page)?;
   770          }
   771  
   772          Ok(())
   773      }
   774  
   775      fn _finalize_record(
   776          &self,
   777          payload: payload::FinalizeRecordAction,
   778          mut state: SupplyChainState,
   779          signer: &str,
   780      ) -> Result<(), ApplyError> {
   781          let record_id = payload.get_record_id();
   782          let final_record = match state.get_record(record_id) {
   783              Ok(Some(final_record)) => final_record,
   784              Ok(None) => {
   785                  return Err(ApplyError::InvalidTransaction(format!(
   786                      "Record does not exist: {}",
   787                      record_id
   788                  )))
   789              }
   790              Err(err) => return Err(err),
   791          };
   792          let owner = match final_record.owners.last() {
   793              Some(x) => x,
   794              None => {
   795                  return Err(ApplyError::InvalidTransaction(String::from(
   796                      "Owner was not found",
   797                  )))
   798              }
   799          };
   800          let custodian = match final_record.custodians.last() {
   801              Some(x) => x,
   802              None => {
   803                  return Err(ApplyError::InvalidTransaction(String::from(
   804                      "Custodian was not found",
   805                  )))
   806              }
   807          };
   808  
   809          if owner.agent_id != signer || custodian.agent_id != signer {
   810              return Err(ApplyError::InvalidTransaction(format!(
   811                  "Must be owner and custodian to finalize record"
   812              )));
   813          }
   814          if final_record.get_field_final() {
   815              return Err(ApplyError::InvalidTransaction(format!(
   816                  "Record is already final: {}",
   817                  record_id
   818              )));
   819          }
   820  
   821          let mut record_clone = final_record.clone();
   822          record_clone.set_field_final(true);
   823          state.set_record(record_id, record_clone)?;
   824  
   825          Ok(())
   826      }
   827  
   828      fn _create_record_type(
   829          &self,
   830          payload: payload::CreateRecordTypeAction,
   831          mut state: SupplyChainState,
   832          signer: &str,
   833      ) -> Result<(), ApplyError> {
   834          match state.get_agent(signer) {
   835              Ok(Some(_)) => (),
   836              Ok(None) => {
   837                  return Err(ApplyError::InvalidTransaction(format!(
   838                      "Agent is not register: {}",
   839                      signer
   840                  )))
   841              }
   842              Err(err) => return Err(err),
   843          }
   844          let name = payload.get_name();
   845          let mut provided_properties: HashMap<&str, property::PropertySchema> = HashMap::new();
   846          for property in payload.get_properties() {
   847              provided_properties.insert(property.get_name(), property.clone());
   848          }
   849          match state.get_record_type(name) {
   850              Ok(Some(_)) => {
   851                  return Err(ApplyError::InvalidTransaction(format!(
   852                      "Record type already exists: {}",
   853                      signer
   854                  )))
   855              }
   856              Ok(None) => (),
   857              Err(err) => return Err(err),
   858          }
   859          let mut record_type = record::RecordType::new();
   860          record_type.set_name(name.to_string());
   861          record_type.set_properties(RepeatedField::from_vec(payload.get_properties().to_vec()));
   862  
   863          state.set_record_type(name, record_type)?;
   864  
   865          Ok(())
   866      }
   867  
   868      fn _update_properties(
   869          &self,
   870          payload: payload::UpdatePropertiesAction,
   871          mut state: SupplyChainState,
   872          signer: &str,
   873          timestamp: u64,
   874      ) -> Result<(), ApplyError> {
   875          let record_id = payload.get_record_id();
   876          let update_record = match state.get_record(record_id) {
   877              Ok(Some(update_record)) => update_record,
   878              Ok(None) => {
   879                  return Err(ApplyError::InvalidTransaction(format!(
   880                      "Record does not exist: {}",
   881                      record_id
   882                  )))
   883              }
   884              Err(err) => return Err(err),
   885          };
   886  
   887          if update_record.get_field_final() {
   888              return Err(ApplyError::InvalidTransaction(format!(
   889                  "Record is final: {}",
   890                  record_id
   891              )));
   892          }
   893  
   894          let updates = payload.get_properties();
   895  
   896          for update in updates {
   897              let name = update.get_name();
   898              let data_type = update.get_data_type();
   899  
   900              let mut prop = match state.get_property(record_id, name) {
   901                  Ok(Some(prop)) => prop,
   902                  Ok(None) => {
   903                      return Err(ApplyError::InvalidTransaction(format!(
   904                          "Record does not have provided poperty: {}",
   905                          name
   906                      )))
   907                  }
   908                  Err(err) => return Err(err),
   909              };
   910  
   911              let mut allowed = false;
   912              let mut reporter_index = 0;
   913              for reporter in prop.get_reporters() {
   914                  if reporter.get_public_key() == signer && reporter.get_authorized() {
   915                      allowed = true;
   916                      reporter_index = reporter.get_index();
   917                      break;
   918                  }
   919              }
   920              if !allowed {
   921                  return Err(ApplyError::InvalidTransaction(format!(
   922                      "Reporter is not authorized: {}",
   923                      signer
   924                  )));
   925              }
   926  
   927              if prop.fixed {
   928                  return Err(ApplyError::InvalidTransaction(format!(
   929                      "Property is fixed and cannot be updated: {}",
   930                      prop.name
   931                  )));
   932              }
   933  
   934              if data_type != prop.data_type {
   935                  return Err(ApplyError::InvalidTransaction(format!(
   936                      "Update has wrong type: {:?} != {:?}",
   937                      data_type, prop.data_type
   938                  )));
   939              }
   940  
   941              let page_number = prop.get_current_page();
   942              let mut page = match state.get_property_page(record_id, name, page_number) {
   943                  Ok(Some(page)) => page,
   944                  Ok(None) => {
   945                      return Err(ApplyError::InvalidTransaction(String::from(
   946                          "Property page does not exist",
   947                      )))
   948                  }
   949                  Err(err) => return Err(err),
   950              };
   951  
   952              let reported_value = match self._make_new_reported_value(
   953                  reporter_index,
   954                  timestamp,
   955                  update,
   956                  &prop,
   957              ) {
   958                  Ok(reported_value) => reported_value,
   959                  Err(err) => return Err(err),
   960              };
   961              page.reported_values.push(reported_value);
   962              page.reported_values
   963                  .sort_by_key(|rv| (rv.clone().timestamp, rv.clone().reporter_index));
   964              state.set_property_page(record_id, name, page_number, page.clone())?;
   965              if page.reported_values.len() >= PROPERTY_PAGE_MAX_LENGTH {
   966                  let mut new_page_number = page_number + 1;
   967                  if page_number + 1 <= PROPERTY_PAGE_MAX_LENGTH as u32 {
   968                      new_page_number = 1;
   969                  }
   970  
   971                  let new_page = match state.get_property_page(record_id, name, new_page_number) {
   972                      Ok(Some(mut new_page)) => {
   973                          new_page.set_reported_values(RepeatedField::from_vec(Vec::new()));
   974                          new_page
   975                      }
   976                      Ok(None) => {
   977                          let mut new_page = property::PropertyPage::new();
   978                          new_page.set_name(name.to_string());
   979                          new_page.set_record_id(record_id.to_string());
   980                          new_page
   981                      }
   982                      Err(err) => return Err(err),
   983                  };
   984                  state.set_property_page(record_id, name, new_page_number, new_page)?;
   985  
   986                  prop.set_current_page(new_page_number);
   987                  if new_page_number == 1 && !prop.get_wrapped() {
   988                      prop.set_wrapped(true);
   989                  }
   990                  state.set_property(record_id, name, prop)?;
   991              }
   992          }
   993  
   994          Ok(())
   995      }
   996  
   997      fn _create_proposal(
   998          &self,
   999          payload: payload::CreateProposalAction,
  1000          mut state: SupplyChainState,
  1001          signer: &str,
  1002          timestamp: u64,
  1003      ) -> Result<(), ApplyError> {
  1004          let record_id = payload.record_id;
  1005          let receiving_agent = payload.receiving_agent;
  1006          let role = payload.role;
  1007          let properties = payload.properties;
  1008  
  1009          match state.get_agent(signer) {
  1010              Ok(Some(agent)) => agent,
  1011              Ok(None) => {
  1012                  return Err(ApplyError::InvalidTransaction(format!(
  1013                      "Issuing agent does not exist: {}",
  1014                      signer
  1015                  )))
  1016              }
  1017              Err(err) => return Err(err),
  1018          };
  1019  
  1020          match state.get_agent(&receiving_agent) {
  1021              Ok(Some(agent)) => agent,
  1022              Ok(None) => {
  1023                  return Err(ApplyError::InvalidTransaction(format!(
  1024                      "Receiving agent does not exist: {}",
  1025                      receiving_agent
  1026                  )))
  1027              }
  1028              Err(err) => return Err(err),
  1029          };
  1030  
  1031          let mut proposals = match state.get_proposal_container(&record_id, &receiving_agent) {
  1032              Ok(Some(proposals)) => proposals,
  1033              Ok(None) => proposal::ProposalContainer::new(),
  1034              Err(err) => return Err(err),
  1035          };
  1036  
  1037          let mut open_proposals = Vec::<proposal::Proposal>::new();
  1038          for prop in proposals.get_entries() {
  1039              if prop.status == proposal::Proposal_Status::OPEN {
  1040                  open_proposals.push(prop.clone());
  1041              }
  1042          }
  1043  
  1044          for prop in open_proposals {
  1045              if prop.get_receiving_agent() == receiving_agent && prop.get_role() == role
  1046                  && prop.get_record_id() == record_id
  1047              {
  1048                  return Err(ApplyError::InvalidTransaction(String::from(
  1049                      "Proposal already exists",
  1050                  )));
  1051              }
  1052          }
  1053  
  1054          let proposal_record = match state.get_record(&record_id) {
  1055              Ok(Some(record)) => record,
  1056              Ok(None) => {
  1057                  return Err(ApplyError::InvalidTransaction(format!(
  1058                      "Record does not exist: {}",
  1059                      record_id
  1060                  )))
  1061              }
  1062              Err(err) => return Err(err),
  1063          };
  1064  
  1065          if proposal_record.get_field_final() {
  1066              return Err(ApplyError::InvalidTransaction(format!(
  1067                  "Record is final: {}",
  1068                  record_id
  1069              )));
  1070          }
  1071  
  1072          if role == proposal::Proposal_Role::OWNER || role == proposal::Proposal_Role::REPORTER {
  1073              let owner = match proposal_record.owners.last() {
  1074                  Some(owner) => owner,
  1075                  None => {
  1076                      return Err(ApplyError::InvalidTransaction(String::from(
  1077                          "Owner not found",
  1078                      )))
  1079                  }
  1080              };
  1081              if owner.get_agent_id() != signer {
  1082                  return Err(ApplyError::InvalidTransaction(String::from(
  1083                      "Only the owner can create a proposal to change ownership",
  1084                  )));
  1085              }
  1086          }
  1087  
  1088          if role == proposal::Proposal_Role::CUSTODIAN {
  1089              let custodian = match proposal_record.custodians.last() {
  1090                  Some(custodian) => custodian,
  1091                  None => {
  1092                      return Err(ApplyError::InvalidTransaction(String::from(
  1093                          "Custodian not found",
  1094                      )))
  1095                  }
  1096              };
  1097  
  1098              if custodian.get_agent_id() != signer {
  1099                  return Err(ApplyError::InvalidTransaction(String::from(
  1100                      "Only the custodian can create a proposal to change custodianship",
  1101                  )));
  1102              }
  1103          }
  1104  
  1105          let mut new_proposal = proposal::Proposal::new();
  1106          new_proposal.set_record_id(record_id.to_string());
  1107          new_proposal.set_timestamp(timestamp);
  1108          new_proposal.set_issuing_agent(signer.to_string());
  1109          new_proposal.set_receiving_agent(receiving_agent.to_string());
  1110          new_proposal.set_role(role);
  1111          new_proposal.set_properties(properties);
  1112          new_proposal.set_status(proposal::Proposal_Status::OPEN);
  1113  
  1114          proposals.entries.push(new_proposal);
  1115          proposals.entries.sort_by_key(|p| {
  1116              (
  1117                  p.clone().record_id,
  1118                  p.clone().receiving_agent,
  1119                  p.clone().timestamp,
  1120              )
  1121          });
  1122          state.set_proposal_container(&record_id, &receiving_agent, proposals)?;
  1123  
  1124          Ok(())
  1125      }
  1126  
  1127      fn _answer_proposal(
  1128          &self,
  1129          payload: payload::AnswerProposalAction,
  1130          mut state: SupplyChainState,
  1131          signer: &str,
  1132          timestamp: u64,
  1133      ) -> Result<(), ApplyError> {
  1134          let record_id = payload.get_record_id();
  1135          let receiving_agent = payload.get_receiving_agent();
  1136          let role = payload.get_role();
  1137          let response = payload.get_response();
  1138  
  1139          let mut proposals = match state.get_proposal_container(record_id, receiving_agent) {
  1140              Ok(Some(proposals)) => proposals,
  1141              Ok(None) => {
  1142                  return Err(ApplyError::InvalidTransaction(String::from(
  1143                      "Proposal does not exist",
  1144                  )))
  1145              }
  1146              Err(err) => return Err(err),
  1147          };
  1148  
  1149          let mut exists = false;
  1150          let mut current_proposal = match proposals.clone().entries.last() {
  1151              Some(current_proposal) => current_proposal.clone(),
  1152              None => {
  1153                  return Err(ApplyError::InvalidTransaction(format!(
  1154                      "No open proposals found for record {} for {}",
  1155                      record_id, receiving_agent
  1156                  )))
  1157              }
  1158          };
  1159  
  1160          let mut proposal_index = 0;
  1161          let mut count = 0;
  1162  
  1163          for prop in proposals.get_entries() {
  1164              if prop.get_receiving_agent() == receiving_agent && prop.get_role() == role
  1165                  && prop.get_record_id() == record_id
  1166                  && prop.status == proposal::Proposal_Status::OPEN
  1167              {
  1168                  current_proposal = prop.clone();
  1169                  exists = true;
  1170                  proposal_index = count;
  1171                  break;
  1172              }
  1173              count = count + 1;
  1174          }
  1175  
  1176          if !exists {
  1177              return Err(ApplyError::InvalidTransaction(format!(
  1178                  "No open proposals found for record {} for {}",
  1179                  record_id, receiving_agent
  1180              )));
  1181          }
  1182  
  1183          match response {
  1184              payload::AnswerProposalAction_Response::CANCEL => {
  1185                  if current_proposal.get_issuing_agent() != signer {
  1186                      return Err(ApplyError::InvalidTransaction(String::from(
  1187                          "Only the issuing agent can cancel a proposal",
  1188                      )));
  1189                  }
  1190                  current_proposal.status = proposal::Proposal_Status::CANCELED;
  1191              }
  1192              payload::AnswerProposalAction_Response::REJECT => {
  1193                  if current_proposal.get_receiving_agent() != signer {
  1194                      return Err(ApplyError::InvalidTransaction(String::from(
  1195                          "Only the receiving agent can reject a proposal",
  1196                      )));
  1197                  }
  1198                  current_proposal.status = proposal::Proposal_Status::REJECTED;
  1199              }
  1200              payload::AnswerProposalAction_Response::ACCEPT => {
  1201                  if current_proposal.get_receiving_agent() != signer {
  1202                      return Err(ApplyError::InvalidTransaction(String::from(
  1203                          "Only the receiving agent can Accept a proposal",
  1204                      )));
  1205                  };
  1206  
  1207                  let mut proposal_record = match state.get_record(record_id) {
  1208                      Ok(Some(record)) => record,
  1209                      Ok(None) => {
  1210                          return Err(ApplyError::InvalidTransaction(format!(
  1211                              "Record in proposal does not exist: {}",
  1212                              record_id
  1213                          )))
  1214                      }
  1215                      Err(err) => return Err(err),
  1216                  };
  1217  
  1218                  let owner = match proposal_record.clone().owners.last() {
  1219                      Some(owner) => owner.clone(),
  1220                      None => {
  1221                          return Err(ApplyError::InvalidTransaction(String::from(
  1222                              "Owner not found",
  1223                          )))
  1224                      }
  1225                  };
  1226  
  1227                  let custodian = match proposal_record.clone().custodians.last() {
  1228                      Some(custodian) => custodian.clone(),
  1229                      None => {
  1230                          return Err(ApplyError::InvalidTransaction(String::from(
  1231                              "Custodian not found",
  1232                          )))
  1233                      }
  1234                  };
  1235  
  1236                  match role {
  1237                      proposal::Proposal_Role::OWNER => {
  1238                          if owner.get_agent_id() != current_proposal.get_issuing_agent() {
  1239                              current_proposal.status = proposal::Proposal_Status::CANCELED;
  1240                              info!("Record owner does not match the issuing agent of the proposal");
  1241                              // remove old proposal and replace with new one
  1242                              proposals.entries.remove(proposal_index);
  1243                              proposals.entries.push(current_proposal);
  1244                              proposals.entries.sort_by_key(|p| {
  1245                                  (
  1246                                      p.clone().record_id,
  1247                                      p.clone().receiving_agent,
  1248                                      p.clone().timestamp,
  1249                                  )
  1250                              });
  1251                              state.set_proposal_container(&record_id, &receiving_agent, proposals)?;
  1252                              return Ok(());
  1253                          }
  1254  
  1255                          let mut new_owner = record::Record_AssociatedAgent::new();
  1256                          new_owner.set_agent_id(receiving_agent.to_string());
  1257                          new_owner.set_timestamp(timestamp);
  1258                          proposal_record.owners.push(new_owner);
  1259                          state.set_record(record_id, proposal_record.clone())?;
  1260  
  1261                          let record_type =
  1262                              match state.get_record_type(proposal_record.get_record_type()) {
  1263                                  Ok(Some(record_type)) => record_type,
  1264                                  Ok(None) => {
  1265                                      return Err(ApplyError::InvalidTransaction(format!(
  1266                                          "RecordType does not exist: {}",
  1267                                          proposal_record.get_record_type()
  1268                                      )))
  1269                                  }
  1270                                  Err(err) => return Err(err),
  1271                              };
  1272  
  1273                          for prop_schema in record_type.get_properties() {
  1274                              let mut prop =
  1275                                  match state.get_property(record_id, prop_schema.get_name()) {
  1276                                      Ok(Some(prop)) => prop,
  1277                                      Ok(None) => {
  1278                                          return Err(ApplyError::InvalidTransaction(String::from(
  1279                                              "Property does not exist",
  1280                                          )))
  1281                                      }
  1282                                      Err(err) => return Err(err),
  1283                                  };
  1284  
  1285                              let mut authorized = false;
  1286                              let mut new_reporters: Vec<
  1287                                  property::Property_Reporter,
  1288                              > = Vec::new();
  1289                              let temp_prob = prop.clone();
  1290                              let reporters = temp_prob.get_reporters();
  1291                              for reporter in reporters {
  1292                                  if reporter.get_public_key() == owner.get_agent_id() {
  1293                                      let mut new_reporter = reporter.clone();
  1294                                      new_reporter.set_authorized(false);
  1295                                      new_reporters.push(new_reporter);
  1296                                  } else if reporter.get_public_key() == receiving_agent {
  1297                                      let mut new_reporter = reporter.clone();
  1298                                      new_reporter.set_authorized(true);
  1299                                      authorized = true;
  1300                                      new_reporters.push(new_reporter);
  1301                                  } else {
  1302                                      new_reporters.push(reporter.clone());
  1303                                  }
  1304                              }
  1305  
  1306                              if !authorized {
  1307                                  let mut reporter = property::Property_Reporter::new();
  1308                                  reporter.set_public_key(receiving_agent.to_string());
  1309                                  reporter.set_authorized(true);
  1310                                  reporter.set_index(prop.reporters.len() as u32);
  1311                                  new_reporters.push(reporter);
  1312                              }
  1313  
  1314                              prop.set_reporters(RepeatedField::from_vec(new_reporters));
  1315                              state.set_property(record_id, prop.get_name(), prop.clone())?;
  1316                          }
  1317                          current_proposal.status = proposal::Proposal_Status::ACCEPTED;
  1318                      }
  1319                      proposal::Proposal_Role::CUSTODIAN => {
  1320                          if custodian.get_agent_id() != current_proposal.get_issuing_agent() {
  1321                              current_proposal.status = proposal::Proposal_Status::CANCELED;
  1322                              info!(
  1323                                  "Record custodian does not match the issuing agent of the proposal"
  1324                              );
  1325                              // remove old proposal and replace with new one
  1326                              proposals.entries.remove(proposal_index);
  1327                              proposals.entries.push(current_proposal.clone());
  1328                              proposals.entries.sort_by_key(|p| {
  1329                                  (
  1330                                      p.clone().record_id,
  1331                                      p.clone().receiving_agent,
  1332                                      p.clone().timestamp,
  1333                                  )
  1334                              });
  1335                              state.set_proposal_container(
  1336                                  &record_id,
  1337                                  &receiving_agent,
  1338                                  proposals.clone(),
  1339                              )?;
  1340                          }
  1341  
  1342                          let mut new_custodian = record::Record_AssociatedAgent::new();
  1343                          new_custodian.set_agent_id(receiving_agent.to_string());
  1344                          new_custodian.set_timestamp(timestamp);
  1345                          proposal_record.custodians.push(new_custodian.clone());
  1346                          state.set_record(record_id, proposal_record)?;
  1347                          current_proposal.status = proposal::Proposal_Status::ACCEPTED;
  1348                      }
  1349                      proposal::Proposal_Role::REPORTER => {
  1350                          if owner.get_agent_id() != current_proposal.get_issuing_agent() {
  1351                              current_proposal.status = proposal::Proposal_Status::CANCELED;
  1352                              info!("Record owner does not match the issuing agent of the proposal");
  1353                              // remove old proposal and replace with new one
  1354                              proposals.entries.remove(proposal_index);
  1355                              proposals.entries.push(current_proposal);
  1356                              proposals.entries.sort_by_key(|p| {
  1357                                  (
  1358                                      p.clone().record_id,
  1359                                      p.clone().receiving_agent,
  1360                                      p.clone().timestamp,
  1361                                  )
  1362                              });
  1363                              state.set_proposal_container(&record_id, &receiving_agent, proposals)?;
  1364                              return Ok(());
  1365                          }
  1366  
  1367                          let mut reporter = property::Property_Reporter::new();
  1368                          reporter.set_public_key(receiving_agent.to_string());
  1369                          reporter.set_authorized(true);
  1370  
  1371                          for prop_name in current_proposal.get_properties() {
  1372                              let mut prop = match state.get_property(record_id, prop_name) {
  1373                                  Ok(Some(prop)) => prop,
  1374                                  Ok(None) => {
  1375                                      return Err(ApplyError::InvalidTransaction(String::from(
  1376                                          "Property does not exist",
  1377                                      )))
  1378                                  }
  1379                                  Err(err) => return Err(err),
  1380                              };
  1381                              reporter.set_index(prop.reporters.len() as u32);
  1382                              prop.reporters.push(reporter.clone());
  1383                              state.set_property(record_id, prop_name, prop)?;
  1384                          }
  1385                          current_proposal.status = proposal::Proposal_Status::ACCEPTED;
  1386                      }
  1387                  }
  1388              }
  1389          }
  1390          // remove old proposal and replace with new one
  1391          proposals.entries.remove(proposal_index);
  1392          proposals.entries.push(current_proposal.clone());
  1393          proposals.entries.sort_by_key(|p| {
  1394              (
  1395                  p.clone().record_id,
  1396                  p.clone().receiving_agent,
  1397                  p.clone().timestamp,
  1398              )
  1399          });
  1400          state.set_proposal_container(&record_id, &receiving_agent, proposals)?;
  1401  
  1402          Ok(())
  1403      }
  1404  
  1405      fn _revoke_reporter(
  1406          &self,
  1407          payload: payload::RevokeReporterAction,
  1408          mut state: SupplyChainState,
  1409          signer: &str,
  1410      ) -> Result<(), ApplyError> {
  1411          let record_id = payload.get_record_id();
  1412          let reporter_id = payload.get_reporter_id();
  1413          let properties = payload.get_properties();
  1414  
  1415          let revoke_record = match state.get_record(record_id) {
  1416              Ok(Some(record)) => record,
  1417              Ok(None) => {
  1418                  return Err(ApplyError::InvalidTransaction(format!(
  1419                      "Record does not exists: {}",
  1420                      record_id
  1421                  )))
  1422              }
  1423              Err(err) => return Err(err),
  1424          };
  1425  
  1426          let owner = match revoke_record.owners.last() {
  1427              Some(x) => x,
  1428              None => {
  1429                  return Err(ApplyError::InvalidTransaction(String::from(
  1430                      "Owner was not found",
  1431                  )))
  1432              }
  1433          };
  1434  
  1435          if owner.get_agent_id() != signer {
  1436              return Err(ApplyError::InvalidTransaction(format!(
  1437                  "Must be owner to revoke reporters"
  1438              )));
  1439          }
  1440  
  1441          if revoke_record.get_field_final() {
  1442              return Err(ApplyError::InvalidTransaction(format!(
  1443                  "Record is final: {}",
  1444                  record_id
  1445              )));
  1446          }
  1447  
  1448          for prop_name in properties {
  1449              let mut prop = match state.get_property(record_id, prop_name) {
  1450                  Ok(Some(prop)) => prop,
  1451                  Ok(None) => {
  1452                      return Err(ApplyError::InvalidTransaction(format!(
  1453                          "Property does not exists"
  1454                      )))
  1455                  }
  1456                  Err(err) => return Err(err),
  1457              };
  1458  
  1459              let mut new_reporters: Vec<property::Property_Reporter> = Vec::new();
  1460              let mut revoked = false;
  1461              for reporter in prop.get_reporters() {
  1462                  if reporter.get_public_key() == reporter_id {
  1463                      if !reporter.get_authorized() {
  1464                          return Err(ApplyError::InvalidTransaction(format!(
  1465                              "Reporter is already unauthorized."
  1466                          )));
  1467                      }
  1468                      let mut unauthorized_reporter = reporter.clone();
  1469                      unauthorized_reporter.set_authorized(false);
  1470                      revoked = true;
  1471                      new_reporters.push(unauthorized_reporter);
  1472                  } else {
  1473                      new_reporters.push(reporter.clone());
  1474                  }
  1475              }
  1476              if !revoked {
  1477                  return Err(ApplyError::InvalidTransaction(format!(
  1478                      "Reporter cannot be revoked: {}",
  1479                      reporter_id
  1480                  )));
  1481              }
  1482              prop.set_reporters(RepeatedField::from_vec(new_reporters));
  1483  
  1484              state.set_property(record_id, prop_name, prop)?;
  1485          }
  1486  
  1487          Ok(())
  1488      }
  1489  
  1490      fn _make_new_reported_value(
  1491          &self,
  1492          reporter_index: u32,
  1493          timestamp: u64,
  1494          value: &property::PropertyValue,
  1495          property: &property::Property,
  1496      ) -> Result<property::PropertyPage_ReportedValue, ApplyError> {
  1497          let mut reported_value = property::PropertyPage_ReportedValue::new();
  1498          reported_value.set_reporter_index(reporter_index);
  1499          reported_value.set_timestamp(timestamp);
  1500  
  1501          match value.get_data_type() {
  1502              property::PropertySchema_DataType::TYPE_UNSET => {
  1503                  return Err(ApplyError::InvalidTransaction(String::from(
  1504                      "DataType is not set",
  1505                  )))
  1506              }
  1507              property::PropertySchema_DataType::BYTES => {
  1508                  reported_value.set_bytes_value(value.get_bytes_value().to_vec())
  1509              }
  1510              property::PropertySchema_DataType::BOOLEAN => {
  1511                  reported_value.set_boolean_value(value.get_boolean_value())
  1512              }
  1513              property::PropertySchema_DataType::NUMBER => {
  1514                  reported_value.set_number_value(value.get_number_value())
  1515              }
  1516              property::PropertySchema_DataType::STRING => {
  1517                  reported_value.set_string_value(value.get_string_value().to_string())
  1518              }
  1519              property::PropertySchema_DataType::ENUM => {
  1520                  let enum_name = value.get_enum_value().to_string();
  1521                  let enum_index = match property.enum_options.iter()
  1522                      .position(|name| name == &enum_name) {
  1523                          Some(index) => index,
  1524                          None => {
  1525                              return Err(ApplyError::InvalidTransaction(format!(
  1526                                  "Provided enum name is not a valid option: {}",
  1527                                  enum_name,
  1528                              )))
  1529                          }
  1530                      };
  1531                  reported_value.set_enum_value(enum_index as u32)
  1532              }
  1533              property::PropertySchema_DataType::STRUCT => {
  1534                  match self._validate_struct_values(
  1535                      &value.struct_values,
  1536                      &property.struct_properties
  1537                  ) {
  1538                      Ok(_) => (),
  1539                      Err(e) => return Err(e),
  1540                  }
  1541  
  1542                  let struct_values = RepeatedField::from_vec(value.get_struct_values().to_vec());
  1543                  reported_value.set_struct_values(struct_values)
  1544              }
  1545              property::PropertySchema_DataType::LOCATION => {
  1546                  reported_value.set_location_value(value.get_location_value().clone())
  1547              }
  1548          };
  1549          Ok(reported_value)
  1550      }
  1551  
  1552      fn _validate_struct_values(
  1553          &self,
  1554          struct_values: &RepeatedField<property::PropertyValue>,
  1555          schema_values: &RepeatedField<property::PropertySchema>
  1556      ) -> Result<(), ApplyError> {
  1557          if struct_values.len() != schema_values.len() {
  1558              return Err(ApplyError::InvalidTransaction(format!(
  1559                  "Provided struct does not match schema length: {:?} != {:?}",
  1560                  struct_values.len(),
  1561                  schema_values.len(),
  1562              )))
  1563          }
  1564  
  1565          for schema in schema_values.iter() {
  1566              let value = match struct_values.iter().find(|val| val.name == schema.name) {
  1567                  Some(val) => val,
  1568                  None => return Err(ApplyError::InvalidTransaction(format!(
  1569                      "Provided struct missing required property from schema: {}",
  1570                      schema.name,
  1571                  )))
  1572              };
  1573  
  1574              if value.data_type != schema.data_type {
  1575                  return Err(ApplyError::InvalidTransaction(format!(
  1576                      "Struct property \"{}\" must have data type: {:?}",
  1577                      schema.name,
  1578                      schema.data_type,
  1579                  )))
  1580              }
  1581  
  1582              if schema.data_type == property::PropertySchema_DataType::STRUCT {
  1583                  match self._validate_struct_values(
  1584                      &value.struct_values,
  1585                      &schema.struct_properties
  1586                  ) {
  1587                      Ok(_) => (),
  1588                      Err(e) => return Err(e),
  1589                  }
  1590              }
  1591          }
  1592  
  1593          Ok(())
  1594      }
  1595  }
  1596  
  1597  impl TransactionHandler for SupplyChainTransactionHandler {
  1598      fn family_name(&self) -> String {
  1599          return self.family_name.clone();
  1600      }
  1601  
  1602      fn family_versions(&self) -> Vec<String> {
  1603          return self.family_versions.clone();
  1604      }
  1605  
  1606      fn namespaces(&self) -> Vec<String> {
  1607          return self.namespaces.clone();
  1608      }
  1609  
  1610      fn apply(
  1611          &self,
  1612          request: &TpProcessRequest,
  1613          context: &mut TransactionContext,
  1614      ) -> Result<(), ApplyError> {
  1615          let payload = SupplyChainPayload::new(request.get_payload());
  1616          let payload = match payload {
  1617              Err(e) => return Err(e),
  1618              Ok(payload) => payload,
  1619          };
  1620          let payload = match payload {
  1621              Some(x) => x,
  1622              None => {
  1623                  return Err(ApplyError::InvalidTransaction(String::from(
  1624                      "Request must contain a payload",
  1625                  )))
  1626              }
  1627          };
  1628  
  1629          let signer = request.get_header().get_signer_public_key();
  1630          let state = SupplyChainState::new(context);
  1631  
  1632          info!(
  1633              "payload: {:?} {} {} {}",
  1634              payload.get_action(),
  1635              payload.get_timestamp(),
  1636              request.get_header().get_inputs()[0],
  1637              request.get_header().get_outputs()[0]
  1638          );
  1639  
  1640          match payload.get_action() {
  1641              Action::CreateAgent(agent_payload) => {
  1642                  self._create_agent(agent_payload, state, signer, payload.get_timestamp())?
  1643              }
  1644              Action::CreateRecord(record_payload) => {
  1645                  self._create_record(record_payload, state, signer, payload.get_timestamp())?
  1646              }
  1647              Action::FinalizeRecord(finalize_payload) => {
  1648                  self._finalize_record(finalize_payload, state, signer)?
  1649              }
  1650              Action::CreateRecordType(record_type_payload) => {
  1651                  self._create_record_type(record_type_payload, state, signer)?
  1652              }
  1653              Action::UpdateProperties(update_properties_payload) => self._update_properties(
  1654                  update_properties_payload,
  1655                  state,
  1656                  signer,
  1657                  payload.get_timestamp(),
  1658              )?,
  1659              Action::CreateProposal(proposal_payload) => {
  1660                  self._create_proposal(proposal_payload, state, signer, payload.get_timestamp())?
  1661              }
  1662              Action::AnswerProposal(answer_proposal_payload) => self._answer_proposal(
  1663                  answer_proposal_payload,
  1664                  state,
  1665                  signer,
  1666                  payload.get_timestamp(),
  1667              )?,
  1668              Action::RevokeReporter(revoke_reporter_payload) => {
  1669                  self._revoke_reporter(revoke_reporter_payload, state, signer)?
  1670              }
  1671          }
  1672          Ok(())
  1673      }
  1674  }