github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/tests/test_genesis/tests.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 # pylint: disable=invalid-name 17 18 import os 19 import shutil 20 import tempfile 21 import unittest 22 from unittest.mock import Mock 23 from unittest.mock import patch 24 25 from sawtooth_signing import create_context 26 from sawtooth_signing import CryptoFactory 27 from sawtooth_validator.database.native_lmdb import NativeLmdbDatabase 28 from sawtooth_validator.database.dict_database import DictDatabase 29 from sawtooth_validator.protobuf.block_pb2 import Block 30 from sawtooth_validator.protobuf.block_pb2 import BlockHeader 31 from sawtooth_validator.protobuf.genesis_pb2 import GenesisData 32 from sawtooth_validator.journal.block_store import BlockStore 33 from sawtooth_validator.journal.block_wrapper import NULL_BLOCK_IDENTIFIER 34 from sawtooth_validator.journal.block_wrapper import BlockWrapper 35 from sawtooth_validator.journal.chain_id_manager import ChainIdManager 36 from sawtooth_validator.journal.genesis import GenesisController 37 from sawtooth_validator.journal.genesis import InvalidGenesisStateError 38 from sawtooth_validator.state.merkle import MerkleDatabase 39 from sawtooth_validator.state.state_view import StateViewFactory 40 41 42 class TestGenesisController(unittest.TestCase): 43 def __init__(self, test_name): 44 super().__init__(test_name) 45 self._temp_dir = None 46 self._signer = None 47 48 def setUp(self): 49 self._temp_dir = tempfile.mkdtemp() 50 context = create_context('secp256k1') 51 private_key = context.new_random_private_key() 52 crypto_factory = CryptoFactory(context) 53 self._signer = crypto_factory.new_signer(private_key) 54 55 def tearDown(self): 56 shutil.rmtree(self._temp_dir) 57 58 @staticmethod 59 def make_block_store(data=None): 60 return BlockStore( 61 DictDatabase( 62 data, indexes=BlockStore.create_index_configuration())) 63 64 def test_requires_genesis(self): 65 self._with_empty_batch_file() 66 67 genesis_ctrl = GenesisController( 68 Mock('context_manager'), 69 Mock('txn_executor'), 70 Mock('completer'), 71 self.make_block_store(), # Empty block store 72 Mock('StateViewFactory'), 73 self._signer, 74 data_dir=self._temp_dir, 75 config_dir=self._temp_dir, 76 chain_id_manager=ChainIdManager(self._temp_dir), 77 batch_sender=Mock('batch_sender')) 78 79 self.assertEqual(True, genesis_ctrl.requires_genesis()) 80 81 def test_does_not_require_genesis_block_exists(self): 82 block = self._create_block() 83 block_store = self.make_block_store({ 84 block.header_signature: block 85 }) 86 87 genesis_ctrl = GenesisController( 88 Mock('context_manager'), 89 Mock('txn_executor'), 90 Mock('completer'), 91 block_store, 92 Mock('StateViewFactory'), 93 self._signer, 94 data_dir=self._temp_dir, 95 config_dir=self._temp_dir, 96 chain_id_manager=ChainIdManager(self._temp_dir), 97 batch_sender=Mock('batch_sender')) 98 99 self.assertEqual(False, genesis_ctrl.requires_genesis()) 100 101 def test_does_not_require_genesis_join_network(self): 102 self._with_network_name('some_network_name') 103 104 block_store = self.make_block_store() 105 106 genesis_ctrl = GenesisController( 107 Mock('context_manager'), 108 Mock('txn_executor'), 109 Mock('completer'), 110 block_store, 111 Mock('StateViewFactory'), 112 self._signer, 113 data_dir=self._temp_dir, 114 config_dir=self._temp_dir, 115 chain_id_manager=ChainIdManager(self._temp_dir), 116 batch_sender=Mock('batch_sender')) 117 118 self.assertEqual(False, genesis_ctrl.requires_genesis()) 119 120 def test_does_not_require_genesis_with_no_file_no_network(self): 121 """ 122 In this case, when there is: 123 - no genesis.batch file 124 - no chain head 125 - no network 126 the the GenesisController should not require genesis. 127 """ 128 block_store = self.make_block_store() 129 130 genesis_ctrl = GenesisController( 131 Mock(name='context_manager'), 132 Mock(name='txn_executor'), 133 Mock('completer'), 134 block_store, 135 Mock('StateViewFactory'), 136 self._signer, 137 data_dir=self._temp_dir, 138 config_dir=self._temp_dir, 139 chain_id_manager=ChainIdManager(self._temp_dir), 140 batch_sender=Mock('batch_sender')) 141 142 self.assertEqual(False, genesis_ctrl.requires_genesis()) 143 144 def test_requires_genesis_fails_if_block_exists(self): 145 """ 146 In this case, when there is 147 - a genesis_batch_file 148 - a chain head id 149 the validator should produce an assertion, as it already has a 150 genesis block and should not attempt to produce another. 151 """ 152 self._with_empty_batch_file() 153 154 block = self._create_block() 155 block_store = self.make_block_store({block.header_signature: block}) 156 157 genesis_ctrl = GenesisController( 158 Mock('context_manager'), 159 Mock('txn_executor'), 160 Mock('completer'), 161 block_store, 162 Mock('StateViewFactory'), 163 self._signer, 164 data_dir=self._temp_dir, 165 config_dir=self._temp_dir, 166 chain_id_manager=ChainIdManager(self._temp_dir), 167 batch_sender=Mock('batch_sender')) 168 169 with self.assertRaises(InvalidGenesisStateError): 170 genesis_ctrl.requires_genesis() 171 172 def test_requires_genesis_fails_if_joins_network_with_file(self): 173 """ 174 In this case, when there is 175 - a genesis_batch_file 176 - network id 177 the validator should produce an assertion error, as it is joining 178 a network, and not a genesis node. 179 """ 180 self._with_empty_batch_file() 181 self._with_network_name('some_block_chain_id') 182 183 block_store = self.make_block_store() 184 185 genesis_ctrl = GenesisController( 186 Mock('context_manager'), 187 Mock('txn_executor'), 188 Mock('completer'), 189 block_store, 190 Mock('StateViewFactory'), 191 self._signer, 192 data_dir=self._temp_dir, 193 config_dir=self._temp_dir, 194 chain_id_manager=ChainIdManager(self._temp_dir), 195 batch_sender=Mock('batch_sender')) 196 197 with self.assertRaises(InvalidGenesisStateError): 198 genesis_ctrl.requires_genesis() 199 200 @patch('sawtooth_validator.execution.scheduler_serial' 201 '.SerialScheduler.complete') 202 def test_empty_batch_file_should_produce_block( 203 self, mock_scheduler_complete 204 ): 205 """ 206 In this case, the genesis batch, even with an empty list of batches, 207 should produce a genesis block. 208 Also: 209 - the genesis.batch file should be deleted 210 - the block_chain_id file should be created and populated 211 """ 212 genesis_file = self._with_empty_batch_file() 213 block_store = self.make_block_store() 214 215 state_database = NativeLmdbDatabase( 216 os.path.join(self._temp_dir, 'test_genesis.lmdb'), 217 indexes=MerkleDatabase.create_index_configuration(), 218 _size=10 * 1024 * 1024) 219 merkle_db = MerkleDatabase(state_database) 220 221 ctx_mgr = Mock(name='ContextManager') 222 ctx_mgr.get_squash_handler.return_value = Mock() 223 ctx_mgr.get_first_root.return_value = merkle_db.get_merkle_root() 224 225 txn_executor = Mock(name='txn_executor') 226 completer = Mock('completer') 227 completer.add_block = Mock('add_block') 228 229 genesis_ctrl = GenesisController( 230 ctx_mgr, 231 txn_executor, 232 completer, 233 block_store, 234 StateViewFactory(state_database), 235 self._signer, 236 data_dir=self._temp_dir, 237 config_dir=self._temp_dir, 238 chain_id_manager=ChainIdManager(self._temp_dir), 239 batch_sender=Mock('batch_sender')) 240 241 on_done_fn = Mock(return_value='') 242 genesis_ctrl.start(on_done_fn) 243 244 self.assertEqual(False, os.path.exists(genesis_file)) 245 246 self.assertEqual(True, block_store.chain_head is not None) 247 self.assertEqual(1, on_done_fn.call_count) 248 self.assertEqual(1, completer.add_block.call_count) 249 self.assertEqual(block_store.chain_head.identifier, 250 self._read_block_chain_id()) 251 252 def _with_empty_batch_file(self): 253 genesis_batch_file = os.path.join(self._temp_dir, 'genesis.batch') 254 with open(genesis_batch_file, 'wb') as f: 255 f.write(GenesisData().SerializeToString()) 256 257 return genesis_batch_file 258 259 def _with_network_name(self, block_chain_id): 260 block_chain_id_file = os.path.join(self._temp_dir, 'block-chain-id') 261 with open(block_chain_id_file, 'w') as f: 262 f.write(block_chain_id) 263 264 return block_chain_id_file 265 266 def _read_block_chain_id(self): 267 block_chain_id_file = os.path.join(self._temp_dir, 'block-chain-id') 268 with open(block_chain_id_file, 'r') as f: 269 return f.read() 270 271 def _create_block(self): 272 return BlockWrapper.wrap( 273 Block( 274 header_signature='some_block_id', 275 batches=[], 276 header=BlockHeader( 277 block_num=0, previous_block_id=NULL_BLOCK_IDENTIFIER) 278 .SerializeToString()))