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