def test_serialize_and_deserialize(self): """ 블럭 serialize and deserialize 테스트 """ block = self.__generate_block() test_dmp = block.serialize_block() block2 = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) block2.deserialize_block(test_dmp) logging.debug("serialize block hash : %s , deserialize block hash %s", block.merkle_tree_root_hash, block2.merkle_tree_root_hash) self.assertEqual(block.merkle_tree_root_hash, block2.merkle_tree_root_hash, "블럭이 같지 않습니다 ")
def generate_test_block(self): """ 임시 블럭 생성하는 메소드 :return: 임시 블럭 """ block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) for x in range(0, 10): tx = test_util.create_basic_tx(self.__peer_id, self.peer_auth) self.assertNotEqual(tx.tx_hash, "", "트랜잭션 생성 실패") self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패") return block
def test_put_transaction(self): """ Block 에 여러 개 transaction 들을 넣는 것을 test. """ block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) tx_list = [] tx_size = 10 for x in range(0, tx_size): tx = test_util.create_basic_tx(self.__peer_id, self.peer_auth) tx2 = test_util.create_basic_tx(self.__peer_id, self.peer_auth) tx_list.append(tx2) self.assertNotEqual(tx.tx_hash, "", "트랜잭션 생성 실패") self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패") self.assertTrue(block.put_transaction(tx_list), "Block에 여러 트랜잭션 추가 실패") self.assertEqual(block.confirmed_tx_len, tx_size * 2, "트랜잭션 사이즈 확인 실패")
def __generate_block_data(self) -> Block: """ block data generate :return: unsigned block """ genesis = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) genesis.generate_block() # Block 생성 block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) # Transaction(s) 추가 for x in range(0, 10): block.put_transaction(test_util.create_basic_tx(self.__peer_id, self.peer_auth)) # Hash 생성 이 작업까지 끝내고 나서 Block을 peer에 보낸다 block.generate_block(genesis) return block
def _deserialize(self, json_data): header_data = self._deserialize_header_data(json_data) header = self.BlockHeaderClass(**header_data) body_data = self._deserialize_body_data(json_data) body = self.BlockBodyClass(**body_data) return Block(header, body)
def add_genesis_block(): tx_info = None channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if "genesis_data_path" in conf.CHANNEL_OPTION[channel]: genesis_data_path = conf.CHANNEL_OPTION[channel][ 'initial_genesis_block_data_file_path'] util.logger.spam( f"Try load a file of initial genesis block from ({genesis_data_path})" ) try: with open(genesis_data_path) as json_file: tx_info = json.load(json_file)["transaction_data"] util.logger.spam( f"generate_genesis_block::tx_info >>>> {tx_info}") except FileNotFoundError as e: exit(f"cannot open json file in ({genesis_data_path}): " f"{e}") block = Block(channel_name=channel) block.block_status = BlockStatus.confirmed genesis_validator = get_genesis_tx_validator(channel) is_valid, tx = genesis_validator.init_genesis_tx(tx_info) if is_valid: block.put_genesis_transaction(tx) block.generate_block() # 제네시스 블럭을 추가 합니다. return block
def test_validate_block(self): """ GIVEN correct block and invalid signature block WHEN validate two block THEN correct block validate return True, invalid block raise exception """ # GIVEN # create correct block block = self.__generate_block() # WHEN THEN self.assertTrue(Block.validate(block), "Fail to validate block!") # GIVEN # create invalid block invalid_signature_block = self.__generate_invalid_block() # WHEN THEN with self.assertRaises(InvalidBlock): Block.validate(invalid_signature_block)
def test_block_hash_must_be_the_same_regardless_of_the_commit_state(self): # ENGINE-302 # GIVEN block1 = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) block2 = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) # WHEN block1.commit_state = {"TEST": "TEST_VALUE1234"} block1.generate_block() block2.generate_block() utils.logger.spam(f"block1 hash({block1.block_hash})") utils.logger.spam(f"block1 hash({block2.block_hash})") # THEN self.assertEqual(block1.block_hash, block2.block_hash)
def test_block_prevent_tx_duplication(self): origin_send_tx_type = conf.CHANNEL_OPTION[ conf.LOOPCHAIN_DEFAULT_CHANNEL]["send_tx_type"] conf.CHANNEL_OPTION[conf.LOOPCHAIN_DEFAULT_CHANNEL][ "send_tx_type"] = conf.SendTxType.icx tx_validator.refresh_tx_validators() try: block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) client = IcxWallet() client.to_address = 'hxebf3a409845cd09dcb5af31ed5be5e34e2af9433' client.value = 1 hash_generator = get_tx_hash_generator( conf.LOOPCHAIN_DEFAULT_CHANNEL) validator = IconValidateStrategy(hash_generator) icx_origin = client.create_icx_origin() for i in range(10): tx = validator.restore(json.dumps(icx_origin), 'icx/score') block.put_transaction(tx) block.generate_block() self.assertEqual(block.confirmed_tx_len, 1) finally: conf.CHANNEL_OPTION[conf.LOOPCHAIN_DEFAULT_CHANNEL][ "send_tx_type"] = origin_send_tx_type tx_validator.refresh_tx_validators()
def test_block_rebuild(self): """ GIVEN 1Block with 3tx, and conf remove failed tx when in block WHEN Block call verify_through_score_invoke THEN all order 3tx must removed in block """ block = Block(conf.LOOPCHAIN_DEFAULT_CHANNEL) fail_tx_hash = None for i in range(3): tx = Transaction() tx.put_meta(Transaction.CHANNEL_KEY, conf.LOOPCHAIN_DEFAULT_CHANNEL) tx.put_data("aaaaa") tx.sign_hash(self.peer_auth) block.put_transaction(tx) if i == 2: fail_tx_hash = tx.tx_hash verify, need_rebuild, invoke_results = block.verify_through_score_invoke(True) self.assertTrue(need_rebuild) logging.debug(f"fail tx hash : {fail_tx_hash}") self.assertEqual(block.confirmed_tx_len, 2) for i, tx in enumerate(block.confirmed_transaction_list): self.assertNotEqual(i, 2, "index 2 must be deleted") self.assertNotEqual(tx.tx_hash, fail_tx_hash)
def test_transaction_merkle_tree_validate_block(self): """ 머클트리 검증 """ # 블럭을 검증 - 모든 머클트리의 내용 검증 block = self.__generate_block_data() mk_result = True for tx in block.confirmed_transaction_list: # FIND tx index idx = block.confirmed_transaction_list.index(tx) sm_result = Block.merkle_path(block, idx) mk_result &= sm_result # logging.debug("Transaction %i th is %s (%s)", idx, sm_result, tx.tx_hash) # logging.debug("block mekletree : %s ", block.merkle_tree) self.assertTrue(mk_result, "머클트리검증 실패")
def __add_single_tx_block_blockchain_return_tx(self): last_block = self.chain.last_block block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) tx = test_util.create_basic_tx(self.__peer_id, self.peer_auth) block.put_transaction(tx) logging.debug("tx_hash: " + tx.tx_hash) block.generate_block(last_block) block.block_status = BlockStatus.confirmed # add_block to blockchain self.assertTrue(self.chain.add_block(block), "Fail Add Block to BlockChain") return tx
class TestGeneratorBlock(unittest.TestCase): """ TODO : rewrite this test class """ last_block = None __peer_id = 'aaa' def setUp(self): self.channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL test_util.print_testname(self._testMethodName) self.peer_auth = Signer.from_prikey(os.urandom(32)) set_mock(self) def tearDown(self): pass def generate_test_block(self): """ 임시 블럭 생성하는 메소드 :return: 임시 블럭 """ if self.last_block is None: self.last_block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) self.last_block.generate_block() block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) for x in range(0, 10): tx = test_util.create_basic_tx(self.__peer_id, self.peer_auth) self.assertNotEqual(tx.tx_hash, "", "트랜잭션 생성 실패") self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패") block.generate_block(self.last_block) self.last_block = block return block def test_block_genesis(self): """ create genesis block """ store_identity = 'genesis_db' chain = BlockChain(self.channel_name, store_id=store_identity) self.assertIsNotNone(chain.get_blockchain_store(), "impossible create DB") block = test_util.add_genesis_block() chain.add_block(block) self.assertIsNotNone(chain.last_block.block_hash, "impossible create genesis block") # remove test DB chain.close_blockchain_store() def test_block_add(self): """ 블럭 추가 테스트 제네시스 블럭을 만든후 10개의 트랜잭션을 가진 10개의 블럭을 생성하여 블럭체인에 추가 """ store_identity = 'add_test_db' # test_store = test_util.make_key_value_store(store_identity) chain = BlockChain(self.channel_name, store_id=store_identity) self.assertIsNotNone(chain.get_blockchain_store(), "impossible create DB") block = test_util.add_genesis_block() chain.add_block(block) genesis_hash = chain.last_block.block_hash for x in range(0,10): # 신규 블럭 생성 추가 x 10 tmp_block = self.generate_test_block() tmp_block.block_status = BlockStatus.confirmed tmp_block.generate_block(chain.last_block) chain.add_block(tmp_block) logging.debug("신규 블럭 생성 및 블럭 HASH : %s", chain.last_block.block_hash) self.assertNotEqual(genesis_hash, chain.last_block.block_hash, "블럭 추가 불가") # 미인증 블럭 추가 tmp_block = self.generate_test_block() tmp_block.block_status = BlockStatus.unconfirmed self.assertRaises(TypeError, "미인증 블럭 추가", chain.add_block, tmp_block) # Store_data Function 추가 tmp_block.block_status = BlockStatus.confirmed tmp_block.generate_block(chain.last_block) # 블럭 저장함수 last_block_hash = chain.last_block.block_hash chain.add_block(tmp_block) self.assertNotEqual(last_block_hash, chain.last_block.block_hash) self.assertIsNotNone(chain.last_block) # remove test DB chain.close_blockchain_store() def test_block_confirm(self): store_identity = 'block_confirm_db' chain = BlockChain(self.channel_name, store_id=store_identity) self.assertIsNotNone(chain.get_blockchain_store(), "impossible create DB") block = test_util.add_genesis_block() chain.add_block(block) self.last_block = block # block을 하나 생성해서 unconfirm 상태에서 추가 unconfirm_block = self.generate_test_block() unconfirm_block.generate_block(chain.last_block) self.assertTrue(chain.add_unconfirm_block(unconfirm_block), "미검증블럭 추가에 실패하였습니다.") # 블럭 검증작업후 블럭을 검증완료 상태로 바꾸며, 블럭체인에 등록 해 줍니다. chain.confirm_prev_block(unconfirm_block) # 블럭 검증완료 self.assertEqual(chain.last_block.block_hash, unconfirm_block.block_hash, "블럭이 추가되지 않았습니다.") chain.close_blockchain_store()
def build_block(self): header = self.BlockHeaderClass(**self.build_block_header_data()) body = self.BlockBodyClass(**self.build_block_body_data()) return Block(header, body)
class TestGeneratorBlock(unittest.TestCase): last_block = None __peer_id = 'aaa' def setUp(self): test_util.print_testname(self._testMethodName) self.peer_auth = Signer.from_prikey(os.urandom(32)) set_mock(self) def tearDown(self): pass def generate_test_block(self): """ 임시 블럭 생성하는 메소드 :return: 임시 블럭 """ if self.last_block is None: self.last_block = Block( channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) self.last_block.generate_block() block = Block(channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL) for x in range(0, 10): tx = test_util.create_basic_tx(self.__peer_id, self.peer_auth) self.assertNotEqual(tx.tx_hash, "", "트랜잭션 생성 실패") self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패") block.generate_block(self.last_block) self.last_block = block return block def test_block_genesis(self): """ 제네시스 블럭 생성 테스트 """ db_name = 'genesis_db' test_db = test_util.make_level_db(db_name) self.assertIsNotNone(test_db, "DB생성 불가") chain = BlockChain(test_db) block = test_util.add_genesis_block() chain.add_block(block) self.assertIsNotNone(chain.last_block.block_hash, "제너릭 블럭 생성 불가") # 테스트 DB 제거 leveldb.DestroyDB(db_name) def test_block_add(self): """ 블럭 추가 테스트 제네시스 블럭을 만든후 10개의 트랜잭션을 가진 10개의 블럭을 생성하여 블럭체인에 추가 """ db_name = 'add_test_db' test_db = test_util.make_level_db(db_name) self.assertIsNotNone(test_db, "DB생성 불가") chain = BlockChain(test_db) block = test_util.add_genesis_block() chain.add_block(block) genesis_hash = chain.last_block.block_hash for x in range(0, 10): # 신규 블럭 생성 추가 x 10 tmp_block = self.generate_test_block() tmp_block.block_status = BlockStatus.confirmed tmp_block.generate_block(chain.last_block) chain.add_block(tmp_block) logging.debug("신규 블럭 생성 및 블럭 HASH : %s", chain.last_block.block_hash) self.assertNotEqual(genesis_hash, chain.last_block.block_hash, "블럭 추가 불가") # 미인증 블럭 추가 tmp_block = self.generate_test_block() tmp_block.block_status = BlockStatus.unconfirmed self.assertRaises(TypeError, "미인증 블럭 추가", chain.add_block, tmp_block) # Store_data Function 추가 tmp_block.block_status = BlockStatus.confirmed tmp_block.generate_block(chain.last_block) # 블럭 저장함수 last_block_hash = chain.last_block.block_hash chain.add_block(tmp_block) self.assertNotEqual(last_block_hash, chain.last_block.block_hash) self.assertIsNotNone(chain.last_block) # 테스트 DB 제거 leveldb.DestroyDB(db_name) def test_block_confirm(self): db_name = 'block_confirm_db' test_db = test_util.make_level_db(db_name) self.assertIsNotNone(test_db, "DB생성 불가") chain = BlockChain(test_db) block = test_util.add_genesis_block() chain.add_block(block) self.last_block = block # block을 하나 생성해서 unconfirm 상태에서 추가 unconfirm_block = self.generate_test_block() unconfirm_block.generate_block(chain.last_block) self.assertTrue(chain.add_unconfirm_block(unconfirm_block), "미검증블럭 추가에 실패하였습니다.") # 블럭 검증작업후 블럭을 검증완료 상태로 바꾸며, 블럭체인에 등록 해 줍니다. chain.confirm_prev_block(unconfirm_block) # 블럭 검증완료 self.assertEqual(chain.last_block.block_hash, unconfirm_block.block_hash, "블럭이 추가되지 않았습니다.") leveldb.DestroyDB(db_name)