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()