예제 #1
0
    def __init_score_helper(self):
        """ Initialize ScoreHelper().

        ScoreHelper is special module to capsulize SCORE operation.
        """

        if self.__score_helper is None:
            self.__score_helper = ScoreHelper()
예제 #2
0
    def test_score_helper_load_databases(self):
        helper = ScoreHelper()
        helper.peer_id = 'test_score_helper_load_databases'
        sqlite_conn = helper.load_database('sqlite_test')
        self.assertIsNotNone(sqlite_conn)
        self.assertIsNotNone(sqlite_conn.cursor())

        leveldb_conn = helper.load_database('leveldb_test',
                                            ScoreDatabaseType.leveldb)
        self.assertIsNotNone(leveldb_conn)
        self.assertIsNotNone(sqlite_conn.cursor())
    def __init_db(self):
        helper = ScoreHelper()
        if self.__contract_db is None:
            logging.debug(self.LOG_PREFIX + "Init DB(%s)", self.CONTRACT_DB_ID)

            self.__contract_db = LocalDB(self.CONTRACT_DB_ID)
        if self.__user_db is None:
            logging.debug(self.LOG_PREFIX + "Init DB(%s)", self.USER_DB_ID)
            self.__user_db = LocalDB(self.USER_DB_ID)
예제 #4
0
    def test_score_helper_load_databases(self, score_service_mock):
        # get peer status Mockup
        score_service_mock.get_peer_status = lambda: json.loads(
            '{"total_tx": "0", "block_height": "0", \
            "status": {"peer_type": "0", "total_tx": 0, "consensus": "siever", "status": "Service is online: 0", \
            "block_height": 0, "audience_count": 0, "peer_id": "d3694dcc-24ff-11e7-b0d1-0242ac110001"}}'
        )
        score_service_mock.get_peer_id = lambda: 'test_score_helper_load_databases'

        ObjectManager().score_service = score_service_mock

        helper = ScoreHelper()
        sqlite_conn = helper.load_database('sqlite_test')
        self.assertIsNotNone(sqlite_conn)
        self.assertIsNotNone(sqlite_conn.cursor())

        leveldb_conn = helper.load_database('leveldb_test', ScoreDatabaseType.leveldb)
        self.assertIsNotNone(leveldb_conn)
        self.assertIsNotNone(sqlite_conn.cursor())
예제 #5
0
 def write_precommit_state(self, params):
     with self.__precommit_usage_lock:
         try:
             commit_request = json.loads(params)
             ScoreHelper().commit_block_state(commit_request['block_height'], commit_request['block_hash'])
             self.__remove_temp_invoke_results(commit_request['block_height'])
             return loopchain_pb2.Message(code=message_code.Response.success)
         except Exception as e:
             logging.exception(f"score db commit error : {params}\n"
                               f"cause : {e}")
             util.exit_and_msg("score db commit fail")
             return loopchain_pb2.Message(code=message_code.Response.fail)
예제 #6
0
    def change_block_hash(self, params):
        with self.__precommit_usage_lock:
            try:
                change_block_info = json.loads(params)
                ScoreHelper().change_block_hash(block_height=change_block_info['block_height'],
                                                old_block_hash=change_block_info['old_block_hash'],
                                                new_block_hash=change_block_info['new_block_hash'])

                self.__remove_fail_invoke_result_to_new_block_invoke_result(change_block_info)

                return loopchain_pb2.Message(code=message_code.Response.success)
            except Exception as e:
                logging.exception(f"score change block hash fail : {params}\n"
                                  f"cause : {e}")
                # change block_hash fail often because next block commit
                # util.exit_and_msg("score db proxy change block_hash fail please restart")
                return loopchain_pb2.Message(code=message_code.Response.fail)
예제 #7
0
    def __init__(self, score_info=None):

        # TODO:Change 'YOUR_SCORE_DB' your own DB name.
        self.__db_name = "YOUR_SCORE_DB"

        # Call base class's __init__.
        ScoreBase.__init__(self, score_info)

        # DO NOT CHANGE THIS BLOCK.
        # ====================================
        # Load package.json file for info() function.
        self.__score_info = None
        if self.__score_info is None:
            with open(join(dirname(__file__), ScoreBase.PACKAGE_FILE),
                      "r") as f:
                self.__score_info = json.loads(f.read())
                f.close()
        else:
            self.__score_info = score_info

        # Initialize ScoreBase module.
        self.__score_helper = ScoreHelper()

        # Initialize SCOREBusinessLogic module.
        self.__my_business_logic = SCOREBusinessLogic()

        # Map functions in package.json.
        for e in self.__score_info["function"]["invoke"]:
            function_name = e["method"]
            self.__invoke_function_map[function_name] = getattr(
                self.__my_business_logic, function_name)

        for e in self.__score_info["function"]["query"]:
            function_name = e["method"]
            self.__query_function_map[function_name] = getattr(
                self.__my_business_logic, function_name)
예제 #8
0
 def __init__(self):
     # User can use several DB instances.
     self.__db = ScoreHelperDatabase("MY_OWN_DB", ScoreHelper())
예제 #9
0
    def genesis_invoke(self, block_pickled):
        logging.debug("ScoreService handler genesis invoke...")
        results = {}
        # dict key

        code_key = 'code'
        error_message_key = 'message'

        if not self._score_service.score:
            logging.error("There is no score!!")
            return loopchain_pb2.Message(code=message_code.Response.fail)
        else:
            block = pickle.loads(block_pickled)
            logging.debug('tx_list_length : %d ', block.confirmed_tx_len)
            ScoreHelper().init_invoke(block)
            for transaction in block.confirmed_transaction_list:
                if isinstance(transaction,
                              Transaction) and transaction.tx_hash is not None:
                    tx_hash = transaction.tx_hash
                    results[tx_hash] = {}
                    # put score invoke result to results[tx_hash]
                    try:
                        plugin_result = self._score_service.score_plugin.genesis_invoke(
                            transaction=transaction, block=block)
                        if plugin_result == PluginReturns.CONTINUE:
                            plugin_result = self._score_service.score.genesis_invoke(
                                transaction, block)
                        invoke_result = plugin_result
                        if invoke_result is None:
                            results[tx_hash] = {
                                code_key: message_code.Response.success
                            }
                            ScoreHelper().commit_tx_state()
                        else:
                            if code_key not in invoke_result:
                                code_not_return = "Score not return code"
                                if error_message_key in invoke_result:
                                    raise ScoreInvokeError(
                                        code_not_return + ": " +
                                        invoke_result[error_message_key])
                                raise ScoreInvokeError(code_not_return)
                            elif invoke_result[
                                    code_key] == message_code.Response.success:
                                ScoreHelper().commit_tx_state()
                            elif error_message_key in invoke_result:
                                results[tx_hash][
                                    error_message_key] = invoke_result[
                                        error_message_key]
                                ScoreHelper().reset_tx_state()
                            results[tx_hash][code_key] = invoke_result[
                                code_key]

                    # if score raise exception result to fail and put error message
                    except Exception as e:
                        logging.exception("tx %s score invoke is fail!! : %s ",
                                          str(tx_hash), e)
                        ScoreHelper().reset_tx_state()
                        results[tx_hash][code_key] = ScoreResponse.EXCEPTION
                        results[tx_hash][error_message_key] = str(e)
                        continue

                    util.apm_event(
                        self._score_service.peer_id, {
                            'event_type': 'GenesisInvoke',
                            'peer_id': self._score_service.peer_id,
                            'peer_name': conf.PEER_NAME,
                            'channel_name': self._score_service.channel_name,
                            'data': {
                                'request_peer_id': None,
                                'tx_data': transaction.get_genesis_tx_data(),
                                'invoke_result': invoke_result
                            }
                        })

            logging.debug('results : %s', str(results))
            ScoreHelper().precommit_state()
            meta = json.dumps(results)
            return loopchain_pb2.Message(code=message_code.Response.success,
                                         meta=meta)
예제 #10
0
    def score_invoke(self, block: Block):
        logging.debug("ScoreService handler invoke...")

        invoke_result_list = {}
        code_key = 'code'
        error_message_key = 'message'

        with self.__precommit_usage_lock:
            if not self._score_service.score:
                logging.error("There is no score!!")
                return loopchain_pb2.Message(code=message_code.Response.fail)
            else:
                # get invoke_data if before invoke same block
                saved_results = self.__temp_invoke_results[block.height].get(
                    block.block_hash)
                logging.debug(
                    f"saved invoke result {block.height}, {block.block_hash} : {saved_results}"
                )
                if saved_results:
                    commit_state = ScoreHelper().get_block_commit_state(
                        block.height, block.block_hash)
                    return loopchain_pb2.Message(
                        code=message_code.Response.success,
                        meta=json.dumps(saved_results),
                        object=pickle.dumps(commit_state))

                logging.debug('tx_list_length : %d ', block.confirmed_tx_len)
                ScoreHelper().init_invoke(block)
                for transaction in block.confirmed_transaction_list:
                    if isinstance(
                            transaction,
                            Transaction) and transaction.tx_hash is not None:
                        tx_hash = transaction.tx_hash
                        invoke_result_list[tx_hash] = {}
                        # put score invoke result to results[tx_hash]
                        invoke_result = {}
                        try:
                            plugin_result = self._score_service.score_plugin.invoke(
                                transaction=transaction, block=block)
                            if plugin_result == PluginReturns.CONTINUE:
                                plugin_result = self._score_service.score.invoke(
                                    transaction, block)
                            invoke_result = plugin_result
                            if invoke_result is None:
                                invoke_result_list[tx_hash] = {
                                    code_key: message_code.Response.success
                                }
                                ScoreHelper().commit_tx_state()
                            else:
                                if code_key not in invoke_result:
                                    code_not_return = "Score not return code"
                                    if error_message_key in invoke_result:
                                        raise ScoreInvokeError(
                                            code_not_return + ": " +
                                            invoke_result[error_message_key])
                                    raise ScoreInvokeError(code_not_return)
                                elif invoke_result[
                                        code_key] == message_code.Response.success:
                                    ScoreHelper().commit_tx_state()
                                elif error_message_key in invoke_result:
                                    invoke_result_list[tx_hash][
                                        error_message_key] = invoke_result[
                                            error_message_key]
                                    ScoreHelper().reset_tx_state()
                                invoke_result_list[tx_hash][
                                    code_key] = invoke_result[code_key]

                        # if score raise exception result to fail and put error message
                        except Exception as e:
                            logging.exception(
                                "tx %s score invoke is fail!! : %s ",
                                str(tx_hash), e)
                            ScoreHelper().reset_tx_state()
                            invoke_result[code_key] = ScoreResponse.EXCEPTION
                            invoke_result[error_message_key] = str(e)
                            invoke_result_list[tx_hash] = invoke_result

                        peer_id = transaction.meta[Transaction.PEER_ID_KEY]

                        util.apm_event(
                            self._score_service.peer_id, {
                                'event_type': 'ScoreInvoke',
                                'peer_id': self._score_service.peer_id,
                                'peer_name': conf.PEER_NAME,
                                'channel_name':
                                self._score_service.channel_name,
                                'data': {
                                    'request_peer_id': peer_id,
                                    'tx_data': transaction.get_data_string(),
                                    'invoke_result': invoke_result
                                }
                            })

                try:
                    self._score_service.iiss_plugin.after_invoke(
                        invoke_result_list=invoke_result_list, block=block)
                except Exception as e:
                    logging.error(f"IISS Plugin Exception({e})")
                    util.exit_and_msg(
                        f"Shutdown Peer by IISS Plugin Exception({e})")

                ScoreHelper().precommit_state()

                self.__temp_invoke_results[block.height][
                    block.block_hash] = invoke_result_list

                if block.confirmed_tx_len > 0:
                    commit_state = ScoreHelper().get_block_commit_state(
                        block.height, block.block_hash)
                else:
                    commit_state = {}

                meta = json.dumps(invoke_result_list)
                return loopchain_pb2.Message(
                    code=message_code.Response.success,
                    meta=meta,
                    object=pickle.dumps(commit_state))
예제 #11
0
class UserScore(ScoreBase):
    """ICX Coin Score code

    ICX SCORE Prototyping code to explain basic SCORE example, NOT OFFICIAL ICX CODE!!!!
    NO GUARANTEE FOR ANY RISK OR TROUBLE.

    """
    __score_info = None
    __db_id = 'icx.db'
    __db = None
    __score_helper = None
    __initialized = False

    def __init__(self, info=None):
        """Initialize SCORE.
        """

        # Initialize SCORE info and DB module.
        self.logi('__init__() start')
        self.__init_score_info(info)
        self.__init_score_helper()
        self.__init_db()
        self.logd('__init__() end')

    def __init_score_info(self, info):
        """ Read package.json file as SCORE package information.

        ScoreHelper is special module to capsulize SCORE operation.
        """
        if info is None:
            with open(dirname(__file__) + '/' + ScoreBase.PACKAGE_FILE,
                      'r') as f:
                self.__score_info = json.loads(f.read())
                f.close()
        else:
            self.__score_info = info

    def __init_score_helper(self):
        """ Initialize ScoreHelper().

        ScoreHelper is special module to capsulize SCORE operation.
        """

        if self.__score_helper is None:
            self.__score_helper = ScoreHelper()

    def __init_db(self):
        """ Initialize database for SCORE.

        SCORE have to store all data into its own database.
        """

        self.logd('__init_db() start')
        if self.__db is None:
            db = self.__score_helper.load_database(
                score_id=self.__db_id, database_type=ScoreDatabaseType.leveldb)
            self.logd(f'db({db}) is created.')
            self.__db = db

        # TESTING purpose.
        # Create virtual bank account ( 0x00000000000000000000000000000000000000000000 ) into 10^22 ICX.
        address = '0x' + '0' * 40
        value = get_balance(self.__db, address)
        if value == 0:
            value = 10**22
            set_balance(self.__db, address, value)
            self.logd(f'address({address}): {value}')

        self.logd('__init_db() end')

    def invoke(self, transaction, block):
        """ Handler of 'Invoke' requests.

        It's event handler of invoke request. You need to implement this handler like below.
        0. Define the interface of functions in 'invoke' field of package.json.
        1. Parse transaction data and get the name of function by reading 'method' field of transaction.
        2. Call that function.

        :param transaction: transaction data.
        :param block: block data has transaction data.
        :return: response : Invoke result.
        """

        self.logd('invoke() start')

        response = None

        try:
            if not verify_transaction(transaction):
                raise IcxError(Code.INVALID_TRANSACTION)

            # Parse transaction data.
            data = transaction.get_data_string()
            params = json.loads(data)
            self.logi(data)

            methods = {
                'icx_init': self.__invoke_init,
                'icx_sendTransaction': self.__invoke_sendTransaction
            }

            method_name = params['method']
            method = methods.get(method_name, None)
            if method is None:
                raise IcxError(Code.METHOD_NOT_FOUND, method_name)

            # Call pre-defined functions in package.json by the request in transaction.
            method(transaction, block, params['params'])

        # Return response code.
        except IcxError as ie:
            response = create_invoke_response(ie.code, ie.message)
        except Exception as e:
            response = create_invoke_response(Code.UnknownError, str(e))
        else:
            response = create_invoke_response(Code.OK)

        self.logi(f'invoke result: {str(response)}')
        self.logd('invoke() end')

        return response

    def __invoke_init(self, transaction, block, params):
        """ Initialize the value of account.

        :param transaction: Transaction data.
        :param block: Block data.
        :param params: params from transaction data including 'address' and'value'.
        """

        self.logd('__invoke_init() start')
        self.logd(f'{str(params)}')

        if self.__initialized:
            raise IcxError(Code.INVALID_TRANSACTION,
                           'icx_score has been already initialized.')

        address = params['address']
        value = params['value']
        set_balance_str(self.__db, address, value)
        self.__initialized = True

        self.logd('__invoke_init() end')

    def __invoke_sendTransaction(self, transaction, block, params):
        """ Transfer money to other's bank account.

        :param transaction: Transaction data.
        :param block: Block data.
        :param params: params from transaction data including 'from', 'to', and 'value'
        """
        self.logd('__invoke_sendTransaction() start')

        from_address = params['from']
        to_address = params['to']
        value = str_to_int(params['value'])

        if value <= 0:
            raise IcxError(Code.INVALID_PARAMS, f'value({value}) is invalid.')

        from_balance = get_balance(self.__db, from_address)
        if from_balance < value:
            raise IcxError(
                Code.INVALID_PARAMS,
                f'from_balance({from_balance}) is less than transaction value({value})'
            )

        to_balance = get_balance(self.__db, to_address)

        from_balance -= value
        to_balance += value

        set_balances(self.__db, {
            from_address: from_balance,
            to_address: to_balance
        })

        self.logd('__invoke_sendTransaction() end')

    def query(self, params):
        """ Handler of 'Query' requests.

        It's event handler of query request. You need to implement this handler like below.
        0. Define the interface of functions in 'query' field of package.json.
        1. Parse transaction data and get the name of function by reading 'method' field of transaction.
        2. Call that function.

        :param transaction: transaction data.
        :param block: block data has transaction data.
        :return: response : Query result.
        """
        self.logd('query() start')
        self.logd('params: ' + str(params))

        _id = None
        response = None

        methods = {'icx_getBalance': self.__query_getBalance}

        try:
            request = json.loads(params)

            _id = request['id']
            method_name = request['method']

            response = methods.get(method_name,
                                   self.__handle_method_not_found)(_id,
                                                                   request)

        except IcxError as ie:
            response = create_jsonrpc_error_response(_id, ie.code, ie.message)
        except Exception as e:
            response = create_jsonrpc_error_response(_id, Code.UnknownError)

        self.logd('query() end')

        return json.dumps(response)

    def __query_getBalance(self, _id, request):
        """ Get the current value of bank account.

        :param _id: ID of request. Used it to distingush request.
        :param request: Request information
        :return:
        """
        self.logd('__query_getBalance() start')
        self.logd(f'{str(request)}')

        params = request['params']
        self.logd(params)
        address = params[0]
        self.logd(address)

        if not check_address(address):
            return create_jsonrpc_error_response(
                _id, Code.INVALID_PARAMS, f'invalid address({address})')

        value = get_balance_str(self.__db, address)
        response = create_jsonrpc_success_response(_id, value)

        self.logd('__query_get_balance() end')

        return response

    def __handle_method_not_found(self, _id, request):
        self.logd('__handle_method_not_found() start')

        method_name = request['method']
        response = create_jsonrpc_error_response(_id, Code.METHOD_NOT_FOUND,
                                                 method_name)

        self.logd('__handle_method_not_found() end')

        return response

    def info(self):
        return self.__score_info

    def log(self, level, message):
        if self.__score_helper:
            self.__score_helper.log("ICX", message, level)

    def logd(self, message):
        self.log(LogLevel.DEBUG, message)

    def logi(self, message):
        self.log(LogLevel.INFO, message)
 def __init__(self, db_name):
     helper = ScoreHelper()
     self.db = helper.load_database(score_id=db_name, database_type=ScoreDatabaseType.leveldb)
예제 #13
0
 def peer_id(self, value):
     self.__peer_id = ScoreHelper().peer_id = value
예제 #14
0
 def __init__(self):
     # User can use several DB instances.
     self.__db = ScoreHelperDatabase("MY_OWN_DB", ScoreHelper())
     self.__db_contract = ScoreHelperDatabase("Contract", ScoreHelper())
     self.__db_Person = ScoreHelperDatabase("Person", ScoreHelper())