Пример #1
0
    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
Пример #2
0
    def test_signature_validate(self):
        """ GIVEN success tx, invalid public key tx, invalid signature tx,
        WHEN validate 3 tx
        THEN only success tx validate return true
        """
        # GIVEN
        # init peer_auth for signautre
        peer_auth = PeerAuthorization(public_file=conf.PUBLIC_PATH,
                                      pri_file=conf.PRIVATE_PATH,
                                      cert_pass=conf.DEFAULT_PW)

        # create txs
        success_tx = test_util.create_basic_tx("aaa", peer_auth)

        # public key and signature property must don't have setter
        invalid_public_tx = test_util.create_basic_tx("aaa", peer_auth)
        invalid_public_tx._Transaction__public_key = b'invalid_public'

        invalid_sign_tx = test_util.create_basic_tx("aaa", peer_auth)
        invalid_sign_tx._Transaction__signature = b'invalid_sign'

        # WHEN THEN
        self.assertTrue(Transaction.validate(success_tx))
        logging.debug("start validate invalid public key")
        self.assertFalse(
            Transaction.validate(invalid_public_tx, is_exception_log=False))
        logging.debug("start validate invalid signature")
        self.assertFalse(
            Transaction.validate(invalid_sign_tx, is_exception_log=False))
Пример #3
0
    def test_put_data(self):
        """트랜잭션 생성확인
        해쉬값의 존재여부

        :return:
        """
        tx = Transaction()
        txhash = tx.put_data("{args:[]}")
        self.assertNotEqual(txhash, "")
Пример #4
0
    def generate_block(self):
        """
        임시 블럭 생성하는 메소드
        :return: 임시 블럭
        """

        block = Block()
        for x in range(10):
            tx = Transaction()
            tx.put_data("{args:[]}")
            block.put_transaction(tx)
        block.generate_block(self.chain.last_block)
        return block
Пример #5
0
 def restore(self, tx_json: str, channel):
     tx = Transaction()
     tx.put_meta(Transaction.SEND_TX_TYPE_KEY, conf.SendTxType.icx)
     tx.put_meta(Transaction.CHANNEL_KEY, channel)
     tx.put_meta(Transaction.METHOD_KEY, self.SEND_TX)
     self.__init_icx_tx(tx_json, tx)
     return tx
Пример #6
0
    def create_tx(self, data):
        tx = Transaction()
        score_id = ""
        score_version = ""

        try:
            score_info = self._channel_service.score_info
            score_id = score_info[message_code.MetaParams.ScoreInfo.score_id]
            score_version = score_info[message_code.MetaParams.ScoreInfo.score_version]
        except KeyError as e:
            logging.debug(f"CreateTX : load score info fail\n"
                          f"cause : {e}")

        send_tx_type = self._channel_service.get_channel_option()["send_tx_type"]
        tx.init_meta(ChannelProperty().peer_id, score_id, score_version, ChannelProperty().name, send_tx_type)
        tx.put_data(data)
        tx.sign_hash(self._channel_service.peer_auth)

        self._channel_service.broadcast_scheduler.schedule_job(BroadcastCommand.CREATE_TX, tx)

        try:
            data_log = json.loads(data)
        except Exception as e:
            data_log = {'tx_hash': tx.tx_hash}

        util.apm_event(ChannelProperty().peer_id, {
            'event_type': 'CreateTx',
            'peer_id': ChannelProperty().peer_id,
            'peer_name': conf.PEER_NAME,
            'channel_name': ChannelProperty().name,
            'tx_hash': tx.tx_hash,
            'data': data_log})

        return tx.tx_hash
Пример #7
0
    def generate_test_block(self):
        """
        임시 블럭 생성하는 메소드
        :return: 임시 블럭
        """

        block = Block()
        for x in range(0, 10):
            tx = Transaction()
            hashed_value = tx.put_data("{args:[]}")
            self.assertNotEqual(hashed_value, "", "트랜잭션 생성 실패")
            self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패")

        return block
Пример #8
0
def create_tx(peer_id: str, data: str, peer_auth: PeerAuthorization) -> Transaction:
    """ create basic tx data is "{args:[]}"

    :param peer_id: peer_id
    :param data: tx_data
    :param peer_auth:
    :return: transaction
    """
    tx = Transaction()
    tx.put_meta('peer_id', peer_id)
    tx.put_meta(Transaction.CHANNEL_KEY, conf.LOOPCHAIN_DEFAULT_CHANNEL)
    tx.put_data(data)
    tx.sign_hash(peer_auth)
    return tx
Пример #9
0
    def test_diff_hash(self):
        """트랜잭션을 생성하여, 같은 값을 입력 하여도 트랜잭션 HASH는 달라야 함
        1000건 생성하여 트랜잭션 비교

        :return:
        """
        sttime = time.time()
        tx_list = []
        test_size = 1000
        for x in range(test_size):
            tx1 = Transaction()
            hashed_value = tx1.put_data("{args:[]}")
            tx_list.append(hashed_value)
        self.assertTrue(len(set(tx_list)) == len(tx_list), "중복된 트랜잭션이 있습니다.")
        logging.debug("test_diff_hash %i times : %f", test_size, time.time() - sttime)
Пример #10
0
    def __add_single_tx_to_block_return_tx_with_test(self):
        last_block = self.chain.last_block
        block = Block()
        tx = Transaction()
        hashed_value = tx.put_data("1234")
        self.assertNotEqual(hashed_value, "", "트랜잭션 생성 실패")
        self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패")

        logging.debug("tx_hash: " + tx.get_tx_hash())

        block.generate_block(last_block)
        block.block_status = BlockStatus.confirmed
        # add_block include __add_tx_to_block_db what we want to test
        self.assertTrue(self.chain.add_block(block),
                        "Fail Add Block to BlockChain in test_add_tx_to_block_db")
        return tx
Пример #11
0
    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.validate(tx):
                tx.status = TransactionStatus.confirmed
            else:
                return False

        # Block 에 검증된 Transaction 추가 : 목록에 존재하는지 확인 필요
        if tx not in self.confirmed_transaction_list:
            self.confirmed_transaction_list.append(tx)
        return True
Пример #12
0
    def test_get_meta_and_put_meta(self):
        # GIVEN
        tx = Transaction()
        tx.put_meta("peer_id", "12345")

        # WHEN
        meta_data = tx.get_meta()
        tx.put_meta("peer_id", "ABCDE")

        # THEN
        logging.debug("tx peer_id(before): " + meta_data["peer_id"])
        logging.debug("tx peer_id(after): " + tx.get_meta()["peer_id"])

        self.assertNotEqual(meta_data["peer_id"], tx.get_meta()["peer_id"])
Пример #13
0
    def generate_block(self):
        """
        블럭 생성기
        :return: 임의생성블럭
        """
        genesis = Block()
        genesis.generate_block()
        # Block 생성
        block = Block()
        # Transaction(s) 추가
        for x in range(0, 10):
            tx = Transaction()
            tx.put_data("{args:[]}")
            block.put_transaction(tx)

        # Hash 생성 이 작업까지 끝내고 나서 Block을 peer에 보낸다
        block.generate_block(genesis)
        return block
Пример #14
0
    def test_dump_tx_size(self):
        # GIVEN
        tx = Transaction()
        tx.put_data("TEST")
        tx.transaction_type = TransactionStatus.confirmed

        tx_only_data = TransactionDataOnly()
        tx_only_data.data = "TEST"

        # WHEN
        dump_a = pickle.dumps(tx_only_data)
        dump_b = pickle.dumps(tx)

        # THEN
        logging.debug("size of tx_only_data: " + str(sys.getsizeof(dump_a)))
        logging.debug("size of tx: " + str(sys.getsizeof(dump_b)))

        self.assertLessEqual(sys.getsizeof(dump_a), sys.getsizeof(dump_b) * 1.5)
Пример #15
0
def create_basic_tx(peer_id: str, peer_auth: PeerAuthorization) -> Transaction:
    """ create basic tx data is "{args:[]}"

    :param peer_id: peer_id
    :param peer_auth:
    :return: transaction
    """
    tx = Transaction()
    tx.put_meta('peer_id', peer_id)
    tx.put_data("{args:[]}")
    tx.sign_hash(peer_auth)
    return tx
    def init_genesis_tx(self, genesis_data: dict):
        # utils.logger.spam(f"genesis_Data :: init_genesis_tx >>>{genesis_data}")
        if genesis_data is None:
            return False, None

        keys = genesis_data.keys()
        if "accounts" not in keys:
            return False, None

        if not self.__validate_params(genesis_data["accounts"]):
            logging.debug(f"Invalid genesis data::accounts")
            return False, None

        tx = Transaction()
        expected_tx_hash = self.hash_generator.generate_hash(genesis_data)
        utils.logger.spam(f"expected_tx_hash::{expected_tx_hash}")
        if not tx.put_genesis_data(genesis_data, expected_tx_hash):
            return False, None

        return True, tx
Пример #17
0
    def test_transaction_performace(self):
        """트랜잭션의 생성 퍼포먼스 1초에 몇개까지 만들 수 있는지 확인
        1초에 5000개 이상

        :return:
        """
        _sttime = time.time()
        tx_list = []

        dummy_data = "TEST Transaction Data"
        put_data = 0
        while time.time() - _sttime < 1.0:
            tx1 = Transaction()
            hashed_value = tx1.put_data("{args:[]}" + (dummy_data + str(put_data)))
            tx_list.append(hashed_value)
            put_data += 1

        self.assertTrue(len(set(tx_list)) == len(tx_list), "중복된 트랜잭션이 있습니다.")
        logging.debug("TX generate %i in a second", len(tx_list))

        self.assertTrue(len(tx_list) > 5000, len(tx_list))
Пример #18
0
    def test_cert_signature(self):
        """GIVEN conf.TX_CERT_AUTH = True, PeerAuthorization create using cert
        WHEN create new tx and create signature
        THEN tx.public_key must be x.509 der cert
        """
        channel_name = "cert_channel"
        conf.CHANNEL_OPTION = {
            channel_name: {
                "load_cert": True,
                "consensus_cert_use": True,
                "tx_cert_use": True,
                "key_load_type": conf.KeyLoadType.FILE_LOAD,
                "public_path": os.path.join(conf.LOOPCHAIN_ROOT_PATH, 'resources/default_certs/cert.pem'),
                "private_path": os.path.join(conf.LOOPCHAIN_ROOT_PATH, 'resources/default_certs/key.pem'),
                "private_password": None
            }
        }
        peer_auth = PeerAuthorization(channel_name)

        # WHEN
        tx = Transaction()
        tx.put_data('{"a":"b"}')
        tx.sign_hash(peer_auth)

        # THEN
        logging.debug(f"tx public key : {tx.public_key}")
        self.assertEqual(tx.public_key, peer_auth.tx_cert)
        # tx.publickey using for load certificate and not raise any error
        x509.load_der_x509_certificate(tx.public_key, default_backend())
Пример #19
0
    def test_tx_json_serialize(self):
        # GIVEN
        tx = Transaction()
        tx.put_data("TEST")
        tx.transaction_type = TransactionStatus.confirmed
        logging.debug(f"transaction for test({tx})")

        # WHEN
        wrap_up = {"__Transaction__": tx}
        serialized = json.dumps(wrap_up, sort_keys=True, cls=CustomEncoder)
        logging.debug(f"serialized tx: {serialized}")

        tx_json = json.loads(serialized, object_hook=decode_object)
        logging.debug(f"deserialized tx: {tx_json}")

        wrap_up_again = {"__Transaction__": tx_json}
        serialized_again = json.dumps(wrap_up_again,
                                      sort_keys=True,
                                      cls=CustomEncoder)
        logging.debug(f"re-serialized tx: {serialized_again}")

        # THEN
        self.assertEqual(serialized, serialized_again)
Пример #20
0
    def validate(block, tx_queue=None) -> bool:
        """validate block and all transactions in block

        :param: block
        :param: tx_queue
        :return validate success return true
        """
        mk_hash = Block.__calculate_merkle_tree_root_hash(block)
        if block.height == 0 and len(block.confirmed_transaction_list) == 0:
            # Genesis Block 은 검증하지 않습니다.
            return True

        if len(block.confirmed_transaction_list) > 0:
            # 머클트리 검증은 Tx가 있을때에만 합니다.
            if mk_hash != block.merkle_tree_root_hash:
                raise BlockInValidError('Merkle Tree Root hash is not same')

        if block.block_hash != Block.__generate_hash(block):
            raise BlockInValidError('block Hash is not same generate hash')

        leader = ObjectManager().peer_service.channel_manager.get_peer_manager(
            block.__channel_name).get_leader_object()
        if not leader.cert_verifier.verify_hash(block.block_hash,
                                                block.signature):
            raise BlockInValidError('block signature invalid')

        if block.time_stamp == 0:
            raise BlockError('block time stamp is 0')

        if len(block.prev_block_hash) == 0:
            raise BlockError('Prev Block Hash not Exist')

        # Transaction Validate
        confirmed_tx_list = []
        for tx in block.confirmed_transaction_list:
            if Transaction.validate(tx):
                confirmed_tx_list.append(tx.tx_hash)
            else:
                raise BlockInValidError(
                    f"block ({block.block_hash}) validate fails \n"
                    f"tx {tx.tx_hash} is invalid")

        if tx_queue is not None:
            block.__tx_validate_with_queue(tx_queue, confirmed_tx_list)

        return True
Пример #21
0
 def test_put_transaction(self):
     """
     Block 에 여러 개 transaction 들을 넣는 것을 test.
     """
     block = Block()
     tx_list = []
     tx_size = 10
     for x in range(0, tx_size):
         tx = Transaction()
         tx2 = Transaction()
         hashed_value = tx.put_data("{args:[]}")
         tx2.put_data("{args:[]}")
         tx_list.append(tx2)
         self.assertNotEqual(hashed_value, "", "트랜잭션 생성 실패")
         self.assertTrue(block.put_transaction(tx), "Block에 트랜잭션 추가 실패")
     self.assertTrue(block.put_transaction(tx_list), "Block에 여러 트랜잭션 추가 실패")
     self.assertEqual(len(block.confirmed_transaction_list), tx_size * 2,
                      "트랜잭션 사이즈 확인 실패")
Пример #22
0
    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
Пример #23
0
 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 restore(self, tx_json):
     tx = Transaction()
     if self.__init_genesis_tx(tx_json, tx):
         return tx
     else:
         return None
Пример #25
0
    def test_generate_and_validate_hash(self):
        """트랜잭션 생성시 만들어진 hash 와 검증시 비교하는 hash 가 동일한지 확인하는 테스트

        :return:
        """
        # GIVEN
        tx = Transaction()
        tx.init_meta("AAAAA", "BBBBB", "CCCCC", conf.LOOPCHAIN_DEFAULT_CHANNEL, conf.SendTxType.pickle)
        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, conf.SendTxType.pickle)
        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 __init_genesis_tx(self, genesis_dumped_data: str, tx: Transaction):
     genesis_data = json.loads(genesis_dumped_data)
     tx_hash = self.hash_generator.generate_hash(genesis_data)
     return tx.put_genesis_data(genesis_data, tx_hash)
Пример #27
0
def decode_object(obj):
    if '__Transaction__' in obj:
        tx = Transaction()
        tx.__dict__.update(obj['__Transaction__'])
        return tx
    return obj
Пример #28
0
 def __init_icx_tx(self, icx_dumped_data: str, tx: Transaction):
     icx_origin_data = json.loads(icx_dumped_data)
     tx.set_icx_origin_data(icx_origin_data, icx_dumped_data)
Пример #29
0
 def restore(self, tx_json: str, channel):
     return Transaction.json_loads(tx_json)