Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Merge pull request #418 from icon-project/IS-1015-tx-number-adjustion…
Browse files Browse the repository at this point in the history
…-in-block

IS-1015: Adjust the number of transactions in a block
  • Loading branch information
Chiwon Cho authored Mar 3, 2020
2 parents 1440a4c + db7ac40 commit 03054af
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 5 deletions.
5 changes: 3 additions & 2 deletions iconservice/icon_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from .icon_constant import (
ConfigKey, ICX_IN_LOOP, TERM_PERIOD, IISS_DAY_BLOCK, PREP_MAIN_PREPS,
PREP_MAIN_AND_SUB_PREPS, PENALTY_GRACE_PERIOD, LOW_PRODUCTIVITY_PENALTY_THRESHOLD,
BLOCK_VALIDATION_PENALTY_THRESHOLD, BACKUP_FILES
BLOCK_VALIDATION_PENALTY_THRESHOLD, BACKUP_FILES, BLOCK_INVOKE_TIMEOUT_S
)

default_icon_config = {
Expand Down Expand Up @@ -61,5 +61,6 @@
ConfigKey.BLOCK_VALIDATION_PENALTY_THRESHOLD: BLOCK_VALIDATION_PENALTY_THRESHOLD,
ConfigKey.STEP_TRACE_FLAG: False,
ConfigKey.PRECOMMIT_DATA_LOG_FLAG: False,
ConfigKey.BACKUP_FILES: BACKUP_FILES
ConfigKey.BACKUP_FILES: BACKUP_FILES,
ConfigKey.BLOCK_INVOKE_TIMEOUT: BLOCK_INVOKE_TIMEOUT_S
}
5 changes: 5 additions & 0 deletions iconservice/icon_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ class ConfigKey:
# The maximum number of backup files for rollback
BACKUP_FILES = "backupFiles"

# Block invoke timeout in second
BLOCK_INVOKE_TIMEOUT = "blockInvokeTimeout"


class EnableThreadFlag(IntFlag):
INVOKE = 1
Expand Down Expand Up @@ -306,6 +309,8 @@ class DeployState(IntEnum):

BACKUP_FILES = 10

BLOCK_INVOKE_TIMEOUT_S = 15


class RCStatus(IntEnum):
NOT_READY = 0
Expand Down
30 changes: 28 additions & 2 deletions iconservice/icon_service_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
ICON_DEX_DB_NAME, ICON_SERVICE_LOG_TAG, IconServiceFlag, ConfigKey,
IISS_METHOD_TABLE, PREP_METHOD_TABLE, NEW_METHOD_TABLE, Revision, BASE_TRANSACTION_INDEX,
IISS_DB, IISS_INITIAL_IREP, DEBUG_METHOD_TABLE, PREP_MAIN_PREPS, PREP_MAIN_AND_SUB_PREPS,
ISCORE_EXCHANGE_RATE, STEP_LOG_TAG, TERM_PERIOD, BlockVoteStatus, WAL_LOG_TAG, ROLLBACK_LOG_TAG
ISCORE_EXCHANGE_RATE, STEP_LOG_TAG, TERM_PERIOD, BlockVoteStatus, WAL_LOG_TAG, ROLLBACK_LOG_TAG,
BLOCK_INVOKE_TIMEOUT_S
)
from .iconscore.icon_pre_validator import IconPreValidator
from .iconscore.icon_score_class_loader import IconScoreClassLoader
Expand Down Expand Up @@ -75,6 +76,7 @@
from .utils import sha3_256, int_to_bytes, ContextEngine, ContextStorage
from .utils import to_camel_case, bytes_to_hex
from .utils.bloom import BloomFilter
from .utils.timer import Timer

if TYPE_CHECKING:
from .iconscore.icon_score_event_log import EventLog
Expand Down Expand Up @@ -112,6 +114,7 @@ def __init__(self):
self._backup_manager: Optional[BackupManager] = None
self._backup_cleaner: Optional[BackupCleaner] = None
self._conf: Optional[Dict[str, Union[str, int]]] = None
self._block_invoke_timeout_s: int = BLOCK_INVOKE_TIMEOUT_S

# JSON-RPC handlers
self._handlers = {
Expand Down Expand Up @@ -215,6 +218,8 @@ def open(self, conf: 'IconConfig'):
context, Address.from_string(conf[ConfigKey.BUILTIN_SCORE_OWNER]))
self._init_global_value_by_governance_score(context)

self._set_block_invoke_timeout(conf)

# DO NOT change the values in conf
self._conf = conf

Expand Down Expand Up @@ -470,7 +475,6 @@ def invoke(self,
:param is_block_editable: boolean which imply whether creating base transaction or not
:return: (TransactionResult[], bytes, added transaction{}, main prep as dict{})
"""

# If the block has already been processed,
# return the result from PrecommitDataManager
precommit_data: 'PrecommitData' = self._precommit_data_manager.get(block.hash)
Expand Down Expand Up @@ -524,7 +528,19 @@ def invoke(self,
context.block_batch.update(context.tx_batch)
context.tx_batch.clear()
else:
tx_timer = Timer()
tx_timer.start()

for index, tx_request in enumerate(tx_requests):
# Adjust the number of transactions in a block to make sure that
# a leader can broadcast a block candidate to validators in a specific period.
if is_block_editable:
if tx_timer.duration >= self._block_invoke_timeout_s:
Logger.info(
tag=self.TAG,
msg=f"Stop to invoke remaining transactions: {index} / {len(tx_requests)}")
break

if index == BASE_TRANSACTION_INDEX and context.is_decentralized():
if not tx_request['params'].get('dataType') == "base":
raise InvalidBaseTransactionException(
Expand Down Expand Up @@ -2388,3 +2404,13 @@ def _finish_to_recover_rollback(self):
end_block_height=metadata.last_block.height - 1)

Logger.debug(tag=self.TAG, msg="_finish_to_recover_rollback() end")

def _set_block_invoke_timeout(self, conf: Dict[str, Union[str, int]]):
try:
timeout_s: int = conf[ConfigKey.BLOCK_INVOKE_TIMEOUT]
if timeout_s > 0:
self._block_invoke_timeout_s = timeout_s
except:
pass

Logger.info(tag=self.TAG, msg=f"{ConfigKey.BLOCK_INVOKE_TIMEOUT}: {self._block_invoke_timeout_s}")
28 changes: 28 additions & 0 deletions iconservice/utils/timer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Copyright 2020 ICON Foundation Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import time


class Timer(object):
def __init__(self):
self._start_time_s: float = 0

@property
def duration(self) -> float:
return time.time() - self._start_time_s

def start(self):
self._start_time_s = time.time()
3 changes: 2 additions & 1 deletion tests/test_icon_score_deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ def test_install(self):
score_deploy_path: str = get_score_deploy_path('/', self.address, tx_hash1)
with self.assertRaises(BaseException) as e:
IconScoreDeployer.deploy(score_deploy_path, self.read_zipfile_as_byte(self.normal_score_path))
self.assertIsInstance(e.exception, PermissionError)
# On MacOS OSError is raised which is different from Linux
# self.assertIsInstance(e.exception, PermissionError)

# Case when the user try to install scores inner directories.
tx_hash3 = create_tx_hash()
Expand Down

0 comments on commit 03054af

Please sign in to comment.