github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/tests/sawtooth_sc_test/supply_chain_message_factory.py (about)

     1  # Copyright 2017 Intel Corporation
     2  # Copyright 2018 Cargill Incorporated
     3  #
     4  # Licensed under the Apache License, Version 2.0 (the "License");
     5  # you may not use this file except in compliance with the License.
     6  # You may obtain a copy of the License at
     7  #
     8  #     http://www.apache.org/licenses/LICENSE-2.0
     9  #
    10  # Unless required by applicable law or agreed to in writing, software
    11  # distributed under the License is distributed on an "AS IS" BASIS,
    12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  # See the License for the specific language governing permissions and
    14  # limitations under the License.
    15  # ------------------------------------------------------------------------------
    16  
    17  import logging
    18  import time
    19  
    20  from sawtooth_processor_test.message_factory import MessageFactory
    21  
    22  from sawtooth_sc_test.protobuf.payload_pb2 import SCPayload
    23  from sawtooth_sc_test.protobuf.payload_pb2 import CreateAgentAction
    24  from sawtooth_sc_test.protobuf.payload_pb2 import CreateProposalAction
    25  from sawtooth_sc_test.protobuf.payload_pb2 import AnswerProposalAction
    26  from sawtooth_sc_test.protobuf.payload_pb2 import CreateRecordAction
    27  from sawtooth_sc_test.protobuf.payload_pb2 import \
    28      CreateRecordTypeAction
    29  from sawtooth_sc_test.protobuf.payload_pb2 import FinalizeRecordAction
    30  from sawtooth_sc_test.protobuf.payload_pb2 import \
    31      UpdatePropertiesAction
    32  from sawtooth_sc_test.protobuf.payload_pb2 import RevokeReporterAction
    33  
    34  from sawtooth_sc_test.protobuf.property_pb2 import PropertySchema
    35  from sawtooth_sc_test.protobuf.property_pb2 import PropertyValue
    36  
    37  import sawtooth_sc_test.addressing as addressing
    38  
    39  
    40  LOGGER = logging.getLogger(__name__)
    41  LOGGER.setLevel(logging.DEBUG)
    42  
    43  
    44  class Enum(object):
    45      """A simple wrapper class to store an enum name with type information"""
    46      def __init__(self, name):
    47          self.value = name
    48  
    49  
    50  class SupplyChainMessageFactory:
    51      def __init__(self, signer=None):
    52          self._factory = MessageFactory(
    53              family_name=addressing.FAMILY_NAME,
    54              family_version='1.1',
    55              namespace=addressing.NAMESPACE,
    56              signer=signer)
    57  
    58          self.public_key = self._factory.get_public_key()
    59          self.signer_address = addressing.make_agent_address(self.public_key)
    60  
    61      def create_agent(self, name):
    62          payload = _make_sc_payload(
    63              action=SCPayload.CREATE_AGENT,
    64              create_agent=CreateAgentAction(name=name))
    65  
    66          return self._create_transaction(
    67              payload,
    68              [self.signer_address],
    69              [self.signer_address],
    70          )
    71  
    72      def create_record_type(self, name, *properties):
    73          def make_schema(name, data_type, attrs):
    74              if 'struct_properties' in attrs:
    75                  attrs['struct_properties'] =\
    76                      [make_schema(n, dt, a)
    77                       for n, dt, a in attrs['struct_properties']]
    78              return PropertySchema(name=name, data_type=data_type, **attrs)
    79  
    80          payload = _make_sc_payload(
    81              action=SCPayload.CREATE_RECORD_TYPE,
    82              create_record_type=CreateRecordTypeAction(
    83                  name=name,
    84                  properties=[make_schema(n, dt, a) for (n, dt, a) in properties]
    85              )
    86          )
    87  
    88          record_type_address = addressing.make_record_type_address(name)
    89  
    90          return self._create_transaction(
    91              payload,
    92              inputs=[record_type_address, self.signer_address],
    93              outputs=[record_type_address],
    94          )
    95  
    96      def create_record(self, record_id, record_type, properties_dict):
    97          payload = _make_sc_payload(
    98              action=SCPayload.CREATE_RECORD,
    99              create_record=CreateRecordAction(
   100                  record_id=record_id,
   101                  record_type=record_type,
   102                  properties=[
   103                      _make_property_value(name, value)
   104                      for name, value in properties_dict.items()
   105                  ]
   106              )
   107          )
   108  
   109          record_address = addressing.make_record_address(record_id)
   110          record_type_address = addressing.make_record_type_address(record_type)
   111          property_address_range = \
   112              addressing.make_property_address_range(record_id)
   113  
   114          inputs = [
   115              record_address,
   116              record_type_address,
   117              property_address_range,
   118              self.signer_address,
   119          ]
   120  
   121          return self._create_transaction(
   122              payload,
   123              inputs=inputs,
   124              outputs=[
   125                  record_address,
   126                  property_address_range,
   127              ]
   128          )
   129  
   130      def finalize_record(self, record_id):
   131          payload = _make_sc_payload(
   132              action=SCPayload.FINALIZE_RECORD,
   133              finalize_record=FinalizeRecordAction(
   134                  record_id=record_id))
   135  
   136          record_address = addressing.make_record_address(record_id)
   137  
   138          return self._create_transaction(
   139              payload,
   140              [record_address],
   141              [record_address]
   142          )
   143  
   144      def update_properties(self, record_id, properties_dict):
   145          payload = _make_sc_payload(
   146              action=SCPayload.UPDATE_PROPERTIES,
   147              update_properties=UpdatePropertiesAction(
   148                  record_id=record_id,
   149                  properties=[
   150                      _make_property_value(name, value)
   151                      for name, value in properties_dict.items()
   152                  ]
   153              )
   154          )
   155  
   156          record_address = addressing.make_record_address(record_id)
   157          property_address_range = \
   158              addressing.make_property_address_range(record_id)
   159  
   160          inputs = [
   161              record_address,
   162              property_address_range,
   163          ]
   164  
   165          return self._create_transaction(
   166              payload,
   167              inputs=inputs,
   168              outputs=[property_address_range]
   169          )
   170  
   171      def create_proposal(self, record_id, receiving_agent,
   172                          role, properties=None):
   173          if properties is None:
   174              properties = []
   175  
   176          payload = _make_sc_payload(
   177              action=SCPayload.CREATE_PROPOSAL,
   178              create_proposal=CreateProposalAction(
   179                  record_id=record_id,
   180                  receiving_agent=receiving_agent,
   181                  role=role,
   182                  properties=properties))
   183  
   184          proposal_address = addressing.make_proposal_address(
   185              record_id,
   186              receiving_agent)
   187  
   188          receiving_address = addressing.make_agent_address(receiving_agent)
   189  
   190          record_address = addressing.make_record_address(record_id)
   191  
   192          return self._create_transaction(
   193              payload,
   194              inputs=[
   195                  proposal_address,
   196                  record_address,
   197                  receiving_address,
   198                  self.signer_address,
   199              ],
   200              outputs=[proposal_address],
   201          )
   202  
   203      def answer_proposal(self, record_id, receiving_agent, role, response):
   204          payload = _make_sc_payload(
   205              action=SCPayload.ANSWER_PROPOSAL,
   206              answer_proposal=AnswerProposalAction(
   207                  record_id=record_id,
   208                  receiving_agent=receiving_agent,
   209                  role=role,
   210                  response=response))
   211  
   212          proposal_address = addressing.make_proposal_address(
   213              record_id,
   214              receiving_agent)
   215  
   216          record_address = addressing.make_record_address(record_id)
   217  
   218          property_address_range = addressing.make_property_address_range(
   219              record_id)
   220  
   221          return self._create_transaction(
   222              payload,
   223              inputs=[
   224                  proposal_address,
   225                  record_address,
   226                  property_address_range,
   227                  addressing.RECORD_TYPE_ADDRESS_RANGE,
   228              ],
   229              outputs=[
   230                  proposal_address,
   231                  record_address,
   232                  property_address_range,
   233              ],
   234          )
   235  
   236      def revoke_reporter(self, record_id, reporter_id, properties):
   237          payload = _make_sc_payload(
   238              action=SCPayload.REVOKE_REPORTER,
   239              revoke_reporter=RevokeReporterAction(
   240                  record_id=record_id,
   241                  reporter_id=reporter_id,
   242                  properties=properties))
   243  
   244          record_address = addressing.make_record_address(record_id)
   245  
   246          proposal_address = addressing.make_proposal_address(
   247              record_id, reporter_id)
   248  
   249          property_addresses = [
   250              addressing.make_property_address(
   251                  record_id, property_name)
   252              for property_name in properties
   253          ]
   254  
   255          return self._create_transaction(
   256              payload,
   257              inputs=[
   258                  record_address,
   259                  proposal_address,
   260                  *property_addresses,
   261              ],
   262              outputs=[
   263                  proposal_address,
   264                  *property_addresses,
   265              ],
   266          )
   267  
   268      def make_empty_payload(self, public_key):
   269          address = addressing.make_agent_address(public_key)
   270  
   271          return self._create_transaction(
   272              payload=SCPayload().SerializeToString(),
   273              inputs=[address],
   274              outputs=[address]
   275          )
   276  
   277      def _create_transaction(self, payload, inputs, outputs):
   278          return self._factory.create_transaction(
   279              payload, inputs, outputs, [])
   280  
   281      def create_batch(self, transaction):
   282          return self._factory.create_batch([transaction])
   283  
   284  
   285  def _make_sc_payload(**kwargs):
   286      return SCPayload(
   287          timestamp=round(time.time()),
   288          **kwargs
   289      ).SerializeToString()
   290  
   291  
   292  def _make_property_value(name, value):
   293      if type(value) == dict:
   294          values = [_make_property_value(k, v) for k, v in value.items()]
   295          return PropertyValue(
   296              name=name,
   297              data_type=PropertySchema.STRUCT,
   298              struct_values=values)
   299  
   300      property_value = PropertyValue(name=name)
   301  
   302      type_slots = {
   303          bool: 'boolean_value',
   304          int: 'number_value',
   305          str: 'string_value',
   306          bytes: 'bytes_value',
   307          Enum: 'enum_value',
   308      }
   309  
   310      type_tags = {
   311          bool: PropertySchema.BOOLEAN,
   312          int: PropertySchema.NUMBER,
   313          str: PropertySchema.STRING,
   314          bytes: PropertySchema.BYTES,
   315          Enum: PropertySchema.ENUM,
   316      }
   317  
   318      try:
   319          value_type = type(value)
   320          slot = type_slots[value_type]
   321          type_tag = type_tags[value_type]
   322      except KeyError:
   323          raise Exception('Unsupported type')
   324  
   325      unwrapped_value = getattr(value, 'value', value)
   326      setattr(property_value, slot, unwrapped_value)
   327      property_value.data_type = type_tag
   328  
   329      return property_value