def validate(self): """블럭 검증 :return: 검증결과 """ mk_hash = self.__calculate_merkle_tree_root_hash() if self.height == 0 and len(self.confirmed_transaction_list) == 0: # Genesis Block 은 검증하지 않습니다. return True if len(self.confirmed_transaction_list) > 0: # 머클트리 검증은 Tx가 있을때에만 합니다. if mk_hash != self.merkle_tree_root_hash: raise BlockInValidError('Merkle Tree Root hash is not same') if self.block_hash != self.__generate_hash(): raise BlockInValidError('block Hash is not same generate hash') if self.time_stamp == 0: raise BlockError('block time stamp is 0') if len(self.prev_block_hash) == 0: raise BlockError('Prev Block Hash not Exist') # Transaction Validate for tx in self.confirmed_transaction_list: if tx.get_tx_hash() != Transaction.generate_transaction_hash(tx): logging.debug("TX HASH : %s vs %s", tx.get_tx_hash(), Transaction.generate_transaction_hash(tx)) raise TransactionInValidError('Transaction hash is not same') return True
def validate(self, tx: Transaction): try: if Transaction.generate_transaction_hash(tx) != tx.tx_hash: self.__logging_tx_validate("hash validate fail", tx) return False # tx = self.__tx_validator() # Get Cert Verifier for signature verify public_verifier = PublicVerifierContainer.get_public_verifier(tx.meta[Transaction.CHANNEL_KEY], tx.public_key) # Signature Validate if public_verifier.verify_hash(tx.tx_hash, tx.signature): return True else: self.__logging_tx_validate("signature validate fail", tx) return False except Exception as e: self.__logging_tx_validate("signature validate fail", tx) return False
def test_generate_and_validate_hash(self): """트랜잭션 생성시 만들어진 hash 와 검증시 비교하는 hash 가 동일한지 확인하는 테스트 :return: """ # GIVEN tx = Transaction() tx.init_meta("AAAAA", "BBBBB", "CCCCC", conf.LOOPCHAIN_DEFAULT_CHANNEL) tx.put_meta("1234", "5678") tx.put_meta("1", "5") tx.put_meta("2", "5") tx.put_meta("3", "5") tx.put_meta("4", "5") txhash1 = tx.put_data("TEST DATA DATA") txtime = tx.get_timestamp() tx2 = Transaction() tx2.init_meta("AAAAA", "BBBBB", "CCCCC", conf.LOOPCHAIN_DEFAULT_CHANNEL) tx2.put_meta("1234", "5678") tx2.put_meta("1", "5") tx2.put_meta("2", "5") tx2.put_meta("3", "5") tx2.put_meta("4", "5") txhash2 = tx2.put_data("TEST DATA DATA", txtime) # WHEN txhash1_1 = Transaction.generate_transaction_hash(tx) # THEN logging.debug("txhash1: " + str(txhash1)) logging.debug("txhash1_1: " + str(txhash1_1)) logging.debug("txhash2: " + str(txhash2)) self.assertEqual(txhash1, txhash2) self.assertEqual(txhash1, txhash1_1) self.assertEqual(txhash2, txhash1_1)
def put_transaction(self, tx): """Block Generator 에서만 사용한다. tx는 단수 혹은 여러개 일 수 있다 :param tx: transaction (transaction을 담고 있는 list도 처리 가능) :return: True: 성공적으로 담겼을 때. """ if type(tx) is list: result = True for t in tx: result &= self.put_transaction(t) return result elif not isinstance(tx, Transaction): logging.error("트랜잭션 타입이 아님 %s", type(tx)) return False # TX 검증은 현재 받아들인 TX의 Hash값(Peer 생성)과 # block generator (leader) 에서 만든 Hash 값이 일치하는지 확인 후 block 에 추가합니다. # TX 는 최초 생성한 Peer 에서 block 에 담겨오는지 여부를 확인 할 때까지 보관해야 합니다. (TODO) if tx.status == TransactionStatus.unconfirmed: # transaction 검증 # logging.debug("Transaction Hash %s", tx.get_tx_hash()) if Transaction.generate_transaction_hash(tx) != tx.get_tx_hash(): # 검증실패 logging.error("검증 실패 \ntx hash : " + tx.get_tx_hash() + "\ntx meta : " + str(tx.get_meta()) + "\ntx data : " + str(tx.get_data())) return False else: tx.status = TransactionStatus.confirmed # Block 에 검증된 Transaction 추가 : 목록에 존재하는지 확인 필요 if tx not in self.confirmed_transaction_list: self.confirmed_transaction_list.append(tx) return True