github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/families/settings/tests/test_tp_settings.py (about)

     1  # Copyright 2017 Intel Corporation
     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  
    16  import hashlib
    17  import base64
    18  
    19  from sawtooth_settings.protobuf.settings_pb2 import SettingCandidates
    20  from sawtooth_settings.protobuf.settings_pb2 import SettingCandidate
    21  from sawtooth_settings.protobuf.settings_pb2 import SettingVote
    22  from sawtooth_settings.protobuf.settings_pb2 import SettingProposal
    23  
    24  from sawtooth_settings_test.settings_message_factory \
    25      import SettingsMessageFactory
    26  
    27  from sawtooth_processor_test.transaction_processor_test_case \
    28      import TransactionProcessorTestCase
    29  
    30  
    31  def _to_hash(value):
    32      return hashlib.sha256(value).hexdigest()
    33  
    34  
    35  EMPTY_CANDIDATES = SettingCandidates(candidates=[]).SerializeToString()
    36  
    37  
    38  class TestSettings(TransactionProcessorTestCase):
    39  
    40      @classmethod
    41      def setUpClass(cls):
    42          super().setUpClass()
    43          cls.factory = SettingsMessageFactory()
    44  
    45      def _expect_get(self, key, value=None):
    46          received = self.validator.expect(
    47              self.factory.create_get_request(key))
    48          self.validator.respond(
    49              self.factory.create_get_response(key, value),
    50              received)
    51  
    52      def _expect_set(self, key, expected_value):
    53          received = self.validator.expect(
    54              self.factory.create_set_request(key, expected_value))
    55          print('sending set response...')
    56          self.validator.respond(
    57              self.factory.create_set_response(key), received)
    58  
    59      def _expect_add_event(self, key):
    60          received = self.validator.expect(
    61              self.factory.create_add_event_request(key))
    62  
    63          self.validator.respond(
    64              self.factory.create_add_event_response(),
    65              received)
    66  
    67      def _expect_ok(self):
    68          self.validator.expect(self.factory.create_tp_response("OK"))
    69  
    70      def _expect_invalid_transaction(self):
    71          self.validator.expect(
    72              self.factory.create_tp_response("INVALID_TRANSACTION"))
    73  
    74      def _expect_internal_error(self):
    75          self.validator.expect(
    76              self.factory.create_tp_response("INTERNAL_ERROR"))
    77  
    78      def _propose(self, key, value):
    79          self.validator.send(self.factory.create_proposal_transaction(
    80              key, value, "somenonce"))
    81  
    82      def _vote(self, proposal_id, setting, vote):
    83          self.validator.send(self.factory.create_vote_proposal(
    84              proposal_id, setting, vote))
    85  
    86      @property
    87      def _public_key(self):
    88          return self.factory.public_key
    89  
    90      def test_set_value_bad_approval_threshold(self):
    91          """
    92          Tests setting an invalid approval_threshold.
    93          """
    94          self._propose("sawtooth.settings.vote.approval_threshold", "foo")
    95  
    96          self._expect_get('sawtooth.settings.vote.authorized_keys',
    97                           self._public_key)
    98          self._expect_get('sawtooth.settings.vote.approval_threshold')
    99  
   100          self._expect_invalid_transaction()
   101  
   102      def test_set_value_too_large_approval_threshold(self):
   103          """
   104          Tests setting an approval_threshold that is larger than the set of
   105          authorized keys.  This should return an invalid transaction.
   106          """
   107          self._propose("sawtooth.settings.vote.approval_threshold", "2")
   108  
   109          self._expect_get('sawtooth.settings.vote.authorized_keys',
   110                           self._public_key)
   111          self._expect_get('sawtooth.settings.vote.approval_threshold')
   112  
   113          self._expect_invalid_transaction()
   114  
   115      def test_set_value_empty_authorized_keys(self):
   116          """
   117          Tests setting an empty set of authorized keys.
   118  
   119          Empty authorized keys should result in an invalid transaction.
   120          """
   121          self._propose("sawtooth.settings.vote.authorized_keys", "")
   122  
   123          self._expect_get('sawtooth.settings.vote.authorized_keys',
   124                           self._public_key)
   125          self._expect_get('sawtooth.settings.vote.approval_threshold')
   126  
   127          self._expect_invalid_transaction()
   128  
   129      def test_allow_set_authorized_keys_when_initially_empty(self):
   130          """Tests that the authorized keys may be set if initially empty.
   131          """
   132          self._propose("sawtooth.settings.vote.authorized_keys",
   133                        self._public_key)
   134  
   135          self._expect_get('sawtooth.settings.vote.authorized_keys')
   136          self._expect_get('sawtooth.settings.vote.approval_threshold')
   137  
   138          # Check that it is set
   139          self._expect_get('sawtooth.settings.vote.authorized_keys')
   140          self._expect_set('sawtooth.settings.vote.authorized_keys',
   141                           self._public_key)
   142  
   143          self._expect_add_event('sawtooth.settings.vote.authorized_keys')
   144  
   145          self._expect_ok()
   146  
   147      def test_reject_settings_when_auth_keys_is_empty(self):
   148          """Tests that when auth keys is empty, only auth keys maybe set.
   149          """
   150          self._propose('my.config.setting', 'myvalue')
   151  
   152          self._expect_get('sawtooth.settings.vote.authorized_keys')
   153          self._expect_get('sawtooth.settings.vote.approval_threshold')
   154  
   155          self._expect_invalid_transaction()
   156  
   157      def test_set_value_proposals(self):
   158          """
   159          Tests setting the value of sawtooth.settings.vote.proposals, which is
   160          only an internally set structure.
   161          """
   162          self._propose('sawtooth.settings.vote.proposals', EMPTY_CANDIDATES)
   163  
   164          self._expect_get('sawtooth.settings.vote.authorized_keys',
   165                           self._public_key)
   166          self._expect_get('sawtooth.settings.vote.approval_threshold')
   167  
   168          self._expect_invalid_transaction()
   169  
   170      def test_propose(self):
   171          """
   172          Tests proposing a value in ballot mode.
   173          """
   174          self._propose('my.config.setting', 'myvalue')
   175  
   176          self._expect_get('sawtooth.settings.vote.authorized_keys',
   177                           self._public_key)
   178          self._expect_get('sawtooth.settings.vote.approval_threshold', '2')
   179          self._expect_get('sawtooth.settings.vote.proposals')
   180  
   181          proposal = SettingProposal(
   182              setting='my.config.setting',
   183              value='myvalue',
   184              nonce='somenonce'
   185          )
   186          proposal_id = _to_hash(proposal.SerializeToString())
   187          record = SettingCandidate.VoteRecord(
   188              public_key=self._public_key,
   189              vote=SettingVote.ACCEPT)
   190          candidate = SettingCandidate(
   191              proposal_id=proposal_id,
   192              proposal=proposal,
   193              votes=[record])
   194  
   195          candidates = SettingCandidates(candidates=[candidate])
   196  
   197          # Get's again to update the entry
   198          self._expect_get('sawtooth.settings.vote.proposals')
   199          self._expect_set('sawtooth.settings.vote.proposals',
   200                           base64.b64encode(candidates.SerializeToString()))
   201  
   202          self._expect_add_event('sawtooth.settings.vote.proposals')
   203  
   204          self._expect_ok()
   205  
   206      def test_vote_approved(self):
   207          """
   208          Tests voting on a given setting, where the setting is approved
   209          """
   210          proposal = SettingProposal(
   211              setting='my.config.setting',
   212              value='myvalue',
   213              nonce='somenonce'
   214          )
   215          proposal_id = _to_hash(proposal.SerializeToString())
   216          record = SettingCandidate.VoteRecord(
   217              public_key="some_other_public_key",
   218              vote=SettingVote.ACCEPT)
   219          candidate = SettingCandidate(
   220              proposal_id=proposal_id,
   221              proposal=proposal,
   222              votes=[record])
   223  
   224          candidates = SettingCandidates(candidates=[candidate])
   225  
   226          self._vote(proposal_id, 'my.config.setting', SettingVote.ACCEPT)
   227  
   228          self._expect_get('sawtooth.settings.vote.authorized_keys',
   229                           self._public_key + ',some_other_public_key')
   230          self._expect_get('sawtooth.settings.vote.proposals',
   231                           base64.b64encode(candidates.SerializeToString()))
   232          self._expect_get('sawtooth.settings.vote.approval_threshold', '2')
   233  
   234          # the vote should pass
   235          self._expect_get('my.config.setting')
   236          self._expect_set('my.config.setting', 'myvalue')
   237  
   238          self._expect_add_event("my.config.setting")
   239  
   240          # expect to update the proposals
   241          self._expect_get('sawtooth.settings.vote.proposals',
   242                           base64.b64encode(candidates.SerializeToString()))
   243          self._expect_set('sawtooth.settings.vote.proposals',
   244                           base64.b64encode(EMPTY_CANDIDATES))
   245  
   246          self._expect_add_event('sawtooth.settings.vote.proposals')
   247  
   248          self._expect_ok()
   249  
   250      def test_vote_counted(self):
   251          """
   252          Tests voting on a given setting, where the vote is counted only.
   253          """
   254          proposal = SettingProposal(
   255              setting='my.config.setting',
   256              value='myvalue',
   257              nonce='somenonce'
   258          )
   259          proposal_id = _to_hash(proposal.SerializeToString())
   260          record = SettingCandidate.VoteRecord(
   261              public_key="some_other_public_key",
   262              vote=SettingVote.ACCEPT)
   263          candidate = SettingCandidate(
   264              proposal_id=proposal_id,
   265              proposal=proposal,
   266              votes=[record])
   267  
   268          candidates = SettingCandidates(candidates=[candidate])
   269  
   270          self._vote(proposal_id, 'my.config.setting', SettingVote.ACCEPT)
   271  
   272          self._expect_get(
   273              'sawtooth.settings.vote.authorized_keys',
   274              self._public_key + ',some_other_public_key,third_public_key')
   275          self._expect_get('sawtooth.settings.vote.proposals',
   276                           base64.b64encode(candidates.SerializeToString()))
   277          self._expect_get('sawtooth.settings.vote.approval_threshold', '3')
   278  
   279          # expect to update the proposals
   280          self._expect_get('sawtooth.settings.vote.proposals',
   281                           base64.b64encode(candidates.SerializeToString()))
   282  
   283          record = SettingCandidate.VoteRecord(
   284              public_key="some_other_public_key",
   285              vote=SettingVote.ACCEPT)
   286          new_record = SettingCandidate.VoteRecord(
   287              public_key=self._public_key,
   288              vote=SettingVote.ACCEPT)
   289          candidate = SettingCandidate(
   290              proposal_id=proposal_id,
   291              proposal=proposal,
   292              votes=[record, new_record])
   293  
   294          updated_candidates = SettingCandidates(candidates=[candidate])
   295          self._expect_set(
   296              'sawtooth.settings.vote.proposals',
   297              base64.b64encode(updated_candidates.SerializeToString()))
   298  
   299          self._expect_add_event('sawtooth.settings.vote.proposals')
   300  
   301          self._expect_ok()
   302  
   303      def test_vote_rejected(self):
   304          """
   305          Tests voting on a given setting, where the setting is rejected.
   306          """
   307          proposal = SettingProposal(
   308              setting='my.config.setting',
   309              value='myvalue',
   310              nonce='somenonce'
   311          )
   312          proposal_id = _to_hash(proposal.SerializeToString())
   313          candidate = SettingCandidate(
   314              proposal_id=proposal_id,
   315              proposal=proposal,
   316              votes=[
   317                  SettingCandidate.VoteRecord(
   318                      public_key='some_other_public_key',
   319                      vote=SettingVote.ACCEPT),
   320                  SettingCandidate.VoteRecord(
   321                      public_key='a_rejectors_public_key',
   322                      vote=SettingVote.REJECT)
   323              ])
   324  
   325          candidates = SettingCandidates(candidates=[candidate])
   326  
   327          self._vote(proposal_id, 'my.config.setting', SettingVote.REJECT)
   328  
   329          self._expect_get(
   330              'sawtooth.settings.vote.authorized_keys',
   331              self._public_key + ',some_other_public_key,a_rejectors_public_key')
   332          self._expect_get('sawtooth.settings.vote.proposals',
   333                           base64.b64encode(candidates.SerializeToString()))
   334          self._expect_get('sawtooth.settings.vote.approval_threshold', '2')
   335  
   336          # expect to update the proposals
   337          self._expect_get('sawtooth.settings.vote.proposals',
   338                           base64.b64encode(candidates.SerializeToString()))
   339          self._expect_set('sawtooth.settings.vote.proposals',
   340                           base64.b64encode(EMPTY_CANDIDATES))
   341  
   342          self._expect_add_event('sawtooth.settings.vote.proposals')
   343  
   344          self._expect_ok()
   345  
   346      def test_vote_rejects_a_tie(self):
   347          """
   348          Tests voting on a given setting, where there is a tie for accept and
   349          for reject, with no remaining auth keys.
   350          """
   351          proposal = SettingProposal(
   352              setting='my.config.setting',
   353              value='myvalue',
   354              nonce='somenonce'
   355          )
   356          proposal_id = _to_hash(proposal.SerializeToString())
   357          candidate = SettingCandidate(
   358              proposal_id=proposal_id,
   359              proposal=proposal,
   360              votes=[
   361                  SettingCandidate.VoteRecord(
   362                      public_key='some_other_public_key',
   363                      vote=SettingVote.ACCEPT),
   364              ])
   365  
   366          candidates = SettingCandidates(candidates=[candidate])
   367  
   368          self._vote(proposal_id, 'my.config.setting', SettingVote.REJECT)
   369  
   370          self._expect_get('sawtooth.settings.vote.authorized_keys',
   371                           self._public_key + ',some_other_public_key')
   372          self._expect_get('sawtooth.settings.vote.proposals',
   373                           base64.b64encode(candidates.SerializeToString()))
   374          self._expect_get('sawtooth.settings.vote.approval_threshold', '2')
   375  
   376          # expect to update the proposals
   377          self._expect_get('sawtooth.settings.vote.proposals',
   378                           base64.b64encode(candidates.SerializeToString()))
   379          self._expect_set('sawtooth.settings.vote.proposals',
   380                           base64.b64encode(EMPTY_CANDIDATES))
   381  
   382          self._expect_add_event('sawtooth.settings.vote.proposals')
   383  
   384          self._expect_ok()
   385  
   386      def test_authorized_keys_accept_no_approval_threshhold(self):
   387          """
   388          Tests setting a value with auth keys and no approval threshhold
   389          """
   390          self._propose("foo.bar.count", "1")
   391  
   392          self._expect_get('sawtooth.settings.vote.authorized_keys',
   393                           'some_key,' + self._public_key)
   394          self._expect_get('sawtooth.settings.vote.approval_threshold')
   395  
   396          # check the old value and set the new one
   397          self._expect_get('foo.bar.count')
   398          self._expect_set('foo.bar.count', '1')
   399  
   400          self._expect_add_event('foo.bar.count')
   401  
   402          self._expect_ok()
   403  
   404      def test_authorized_keys_wrong_key_no_approval(self):
   405          """
   406          Tests setting a value with a non-authorized key and no approval type
   407          """
   408          self._propose("foo.bar.count", "1")
   409  
   410          self._expect_get('sawtooth.settings.vote.authorized_keys',
   411                           'some_key,some_other_key')
   412  
   413          self._expect_invalid_transaction()