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

IS-1049: Fix some conflicts on merging master to develop #436

Merged
merged 22 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
982f7fb
Merge pull request #405 from icon-project/release-1.6.0
Jan 20, 2020
1440a4c
VERSION: 1.6.1
goldworm-icon Feb 29, 2020
5915cc6
Adjust the number of transactions in a block
goldworm-icon Feb 29, 2020
454d69f
IS-1021: DictDB iteration causes infinite loop
cow-hs Mar 2, 2020
db7ac40
Optimize Timer class
Mar 2, 2020
03054af
Merge pull request #418 from icon-project/IS-1015-tx-number-adjustion…
Mar 3, 2020
16f850f
apply feedback
cow-hs Mar 5, 2020
927f69e
Add sha_256 function for SCORE development
goldworm-icon Mar 4, 2020
a09f612
Merge pull request #422 from icon-project/IS-1024-sha-256-score-func-…
Mar 5, 2020
728fb20
Merge pull request #420 from icon-project/IS-1021-dict-db-iteration-c…
Mar 6, 2020
d13fbb9
IS-1029: Array Optimization hotfix (#424)
cow-hs Mar 11, 2020
6827daa
VERSION: 1.6.1rc1
goldworm-icon Mar 16, 2020
2713c66
Replace time.time() with time.monotonic() in Timer class (#427)
cow-hs Mar 20, 2020
f93ddeb
Skip EOA to EOA icx transfer in execution time check (#428)
cow-hs Mar 20, 2020
2767eec
apply static version about msgpack, iso3166 for migration temporarily
cow-hs Mar 20, 2020
84e75f0
VERSION: 1.6.1rc2
cow-hs Mar 20, 2020
9774fa2
IS-1042 fix Fee 2.0 bug
Mar 24, 2020
9045389
Merge pull request #429 from icon-project/IS-1042-fix-fee2-error-with…
Mar 24, 2020
1a320c5
VERSION: 1.6.1rc3
yakkle Mar 24, 2020
56b3460
VERSION: 1.6.1
goldworm-icon Apr 1, 2020
eefc37c
Merge pull request #434 from icon-project/release-1.6.1
goldworm-icon Apr 1, 2020
0fbc4ab
Merge branch 'master' into IS-1049-merge-hotfix-1-6-1
goldworm-icon Apr 8, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.6.0
1.6.1
2 changes: 1 addition & 1 deletion iconservice/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .icon_constant import IconServiceFlag, IconNetworkValueType
from .iconscore.icon_container_db import VarDB, DictDB, ArrayDB
from .iconscore.icon_score_base import interface, eventlog, external, payable, IconScoreBase, IconScoreDatabase
from .iconscore.icon_score_base2 import (InterfaceScore, revert, sha3_256, json_loads, json_dumps,
from .iconscore.icon_score_base2 import (InterfaceScore, revert, sha3_256, sha_256, json_loads, json_dumps,
get_main_prep_info, get_sub_prep_info, recover_key,
create_address_with_key, create_interface_score)
from .iconscore.icon_system_score_base import IconSystemScoreBase
Expand Down
34 changes: 21 additions & 13 deletions iconservice/database/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from typing import TYPE_CHECKING, Optional, Tuple, Iterable

import plyvel

from iconcommons.logger import Logger

from .batch import TransactionBatchValue
from ..base.exception import DatabaseException, InvalidParamsException, AccessDeniedException
from ..icon_constant import ICON_DB_LOG_TAG, IconScoreContextType
Expand Down Expand Up @@ -384,6 +384,14 @@ def __init__(self,
self._context_db = context_db
self._observer: Optional[DatabaseObserver] = None

self._prefix_hash_key: bytes = self._make_prefix_hash_key()

def _make_prefix_hash_key(self) -> bytes:
data = [self.address.to_bytes()]
if self._prefix is not None:
data.append(self._prefix)
return b'|'.join(data)

def get(self, key: bytes) -> bytes:
"""
Gets the value for the specified key
Expand Down Expand Up @@ -428,7 +436,7 @@ def get_sub_db(self, prefix: bytes) -> 'IconScoreSubDatabase':
'prefix is None in IconScoreDatabase.get_sub_db()')

if self._prefix is not None:
prefix = b'|'.join([self._prefix, prefix])
prefix = b'|'.join((self._prefix, prefix))

return IconScoreSubDatabase(self.address, self, prefix)

Expand Down Expand Up @@ -460,12 +468,8 @@ def _hash_key(self, key: bytes) -> bytes:
:params key: key passed by SCORE
:return: key bytes
"""
data = [self.address.to_bytes()]
if self._prefix is not None:
data.append(self._prefix)
data.append(key)

return b'|'.join(data)
return b'|'.join((self._prefix_hash_key, key))

def _validate_ownership(self):
"""Prevent a SCORE from accessing the database of another SCORE
Expand All @@ -490,6 +494,14 @@ def __init__(self, address: 'Address', score_db: 'IconScoreDatabase', prefix: by
self._prefix = prefix
self._score_db = score_db

self._prefix_hash_key: bytes = self._make_prefix_hash_key()

def _make_prefix_hash_key(self) -> bytes:
data = []
if self._prefix is not None:
data.append(self._prefix)
return b'|'.join(data)

def get(self, key: bytes) -> bytes:
"""
Gets the value for the specified key
Expand Down Expand Up @@ -521,7 +533,7 @@ def get_sub_db(self, prefix: bytes) -> 'IconScoreSubDatabase':
raise InvalidParamsException("Invalid prefix")

if self._prefix is not None:
prefix = b'|'.join([self._prefix, prefix])
prefix = b'|'.join((self._prefix, prefix))

return IconScoreSubDatabase(self.address, self._score_db, prefix)

Expand All @@ -544,9 +556,5 @@ def _hash_key(self, key: bytes) -> bytes:
:params key: key passed by SCORE
:return: key bytes
"""
data = []
if self._prefix is not None:
data.append(self._prefix)
data.append(key)

return b'|'.join(data)
return b'|'.join((self._prefix_hash_key, key))
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 @@ -194,6 +194,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 @@ -300,6 +303,8 @@ class DeployState(IntEnum):

BACKUP_FILES = 10

BLOCK_INVOKE_TIMEOUT_S = 15


class RCStatus(IntEnum):
NOT_READY = 0
Expand Down
61 changes: 55 additions & 6 deletions iconservice/icon_service_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing import TYPE_CHECKING, List, Any, Optional, Tuple, Dict, Union

from iconcommons.logger import Logger

from iconservice.rollback import check_backup_exists
from iconservice.rollback.backup_cleaner import BackupCleaner
from iconservice.rollback.backup_manager import BackupManager
Expand Down Expand Up @@ -46,8 +47,8 @@
Revision, BASE_TRANSACTION_INDEX,
IISS_DB, IISS_INITIAL_IREP, PREP_MAIN_PREPS, PREP_MAIN_AND_SUB_PREPS,
STEP_LOG_TAG, TERM_PERIOD, BlockVoteStatus, WAL_LOG_TAG, ROLLBACK_LOG_TAG,
RevisionChangedFlag)
from .inv import INVEngine, INVStorage
BLOCK_INVOKE_TIMEOUT_S, RevisionChangedFlag
)
from .iconscore.context.context import ContextContainer
from .iconscore.icon_pre_validator import IconPreValidator
from .iconscore.icon_score_context import IconScoreContext, IconScoreFuncType, IconScoreContextFactory
Expand All @@ -68,6 +69,7 @@
from .iiss.reward_calc.storage import IissDBNameRefactor
from .iiss.reward_calc.storage import RewardCalcDBInfo
from .inner_call import inner_call
from .inv import INVEngine, INVStorage
from .meta import MetaDBStorage
from .precommit_data_manager import PrecommitData, PrecommitDataManager
from .prep import PRepEngine, PRepStorage
Expand All @@ -77,6 +79,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 @@ -109,6 +112,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 @@ -207,6 +211,8 @@ def open(self, conf: dict):

context.engine.inv.load_inv_container(context)

self._set_block_invoke_timeout(conf)

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

Expand Down Expand Up @@ -374,7 +380,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 @@ -428,7 +433,18 @@ 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 and not self._continue_to_invoke(tx_request, tx_timer):
Logger.info(
tag=_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 @@ -936,7 +952,6 @@ def _estimate_step_by_execution(self, request, context) -> int:

:param request:
:param context:
:param step_limit:
"""
method: str = request['method']
params: dict = request['params']
Expand Down Expand Up @@ -1131,10 +1146,11 @@ def _handle_icx_get_total_supply(cls,
"""
return context.storage.icx.get_total_supply(context)

def _handle_icx_call(self,
@classmethod
def _handle_icx_call(cls,
context: 'IconScoreContext',
params: dict) -> object:
"""Handles an icx_call jsonrpc request
"""Handles an icx_call json-rpc request

State change is possible in icx_call message

Expand Down Expand Up @@ -2039,3 +2055,36 @@ def _finish_to_recover_rollback(self):
end_block_height=metadata.last_block.height - 1)

Logger.debug(tag=_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=_TAG, msg=f"{ConfigKey.BLOCK_INVOKE_TIMEOUT}: {self._block_invoke_timeout_s}")

def _continue_to_invoke(self, tx_request: Dict, tx_timer: 'Timer') -> bool:
"""If this is a block created by a leader,
check to continue transaction invoking with block_invoke_timeout

:param tx_request:
:param tx_timer:
:return:
"""
to: Optional['Address'] = tx_request["params"].get("to")

# Skip EOA to EOA coin transfer in execution time check
if to and to.is_contract:
if tx_timer.duration >= self._block_invoke_timeout_s:
Logger.info(
tag=_TAG,
msg=f"Stop transaction invoking: "
f"duration={tx_timer.duration} "
f"block_invoke_timeout={self._block_invoke_timeout_s}"
)
return False

return True
Loading