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

Commit

Permalink
Implement shutdown feature
Browse files Browse the repository at this point in the history
* Pass is_shutdown to loopchain when revision has just been changed to Revision.SHUTDOWN(13)
* Fix integrate-test errors
* Add is_shutdown property to PrecommitData
  • Loading branch information
goldworm committed Aug 10, 2021
1 parent 4aaba41 commit a4fc0c6
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 87 deletions.
4 changes: 3 additions & 1 deletion iconservice/icon_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ class Revision(Enum):
VERIFY_ASSET_INTEGRITY = 12
USE_RLP = 12

LATEST = 12
SHUTDOWN = 13

LATEST = 13


RC_DB_VERSION_0 = 0
Expand Down
18 changes: 11 additions & 7 deletions iconservice/icon_inner_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,15 @@ def _invoke(self, request: dict):
converted_prev_block_validators = params.get('prevBlockValidators')
converted_prev_votes = params.get('prevBlockVotes')

tx_results, state_root_hash, added_transactions, next_preps = self._icon_service_engine.invoke(
block=block,
tx_requests=converted_tx_requests,
prev_block_generator=converted_prev_block_generator,
prev_block_validators=converted_prev_block_validators,
prev_block_votes=converted_prev_votes,
is_block_editable=converted_is_block_editable)
tx_results, state_root_hash, added_transactions, next_preps, is_shutdown = \
self._icon_service_engine.invoke(
block=block,
tx_requests=converted_tx_requests,
prev_block_generator=converted_prev_block_generator,
prev_block_validators=converted_prev_block_validators,
prev_block_votes=converted_prev_votes,
is_block_editable=converted_is_block_editable
)

if convert_tx_result_to_dict:
convert_tx_results = [tx_result.to_dict(to_camel_case) for tx_result in tx_results]
Expand All @@ -194,6 +196,8 @@ def _invoke(self, request: dict):

if next_preps:
results["prep"] = next_preps
if is_shutdown:
results["is_shutdown"] = True

response = MakeResponse.make_response(results)
except FatalException as e:
Expand Down
37 changes: 20 additions & 17 deletions iconservice/icon_service_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ def invoke(self,
prev_block_generator: Optional['Address'] = None,
prev_block_validators: Optional[List['Address']] = None,
prev_block_votes: Optional[List[Tuple['Address', int]]] = None,
is_block_editable: bool = False) -> Tuple[List['TransactionResult'], bytes, dict, Optional[dict]]:
is_block_editable: bool = False) -> Tuple[List['TransactionResult'], bytes, dict, Optional[dict], bool]:

"""Process transactions in a block sent by loopchain
Expand All @@ -406,7 +406,7 @@ def invoke(self,
:param prev_block_validators: previous block validators (legacy)
:param prev_block_votes: previous block vote info
:param is_block_editable: boolean which imply whether creating base transaction or not
:return: (TransactionResult[], bytes, added transaction{}, main prep as dict{})
:return: (TransactionResult[], bytes, added transaction{}, main prep as dict{}, is_shutdown)
"""
# If the block has already been processed,
# return the result from PrecommitDataManager
Expand All @@ -422,11 +422,7 @@ def invoke(self,
msg=f"Block result already exists: \n"
f"state_root_hash={bytes_to_hex(precommit_data.state_root_hash)}")

return \
precommit_data.block_result, \
precommit_data.state_root_hash, \
precommit_data.added_transactions, \
precommit_data.next_preps
return _get_invoke_result_from_precommit_data(precommit_data)

# Check for block validation before invoke
self._precommit_data_manager.validate_block_to_invoke(block)
Expand Down Expand Up @@ -563,16 +559,12 @@ def invoke(self,
rc_state_hash,
added_transactions,
next_preps,
context.prep_address_converter)
context.prep_address_converter,
context.is_revision_changed(Revision.SHUTDOWN.value))
if context.precommitdata_log_flag:
Logger.info(tag=_TAG,
msg=f"Created precommit_data: \n{precommit_data}")
Logger.info(tag=_TAG, msg=f"Created precommit_data: \n{precommit_data}")
self._precommit_data_manager.push(precommit_data)
return \
block_result, \
precommit_data.state_root_hash, \
precommit_data.added_transactions, \
precommit_data.next_preps
return _get_invoke_result_from_precommit_data(precommit_data)

@classmethod
def _get_rc_db_revision_before_process_transactions(cls, context: 'IconScoreContext') -> int:
Expand Down Expand Up @@ -1487,8 +1479,8 @@ def _check_contract_call_step(context: 'IconScoreContext',
# - dataType is not 'call'
if to == SYSTEM_SCORE_ADDRESS:
return (
context.revision < Revision.SYSTEM_SCORE_ENABLED.value
and data_type != DataType.CALL
context.revision < Revision.SYSTEM_SCORE_ENABLED.value
and data_type != DataType.CALL
)

return True
Expand Down Expand Up @@ -2255,3 +2247,14 @@ def _handle_debug_get_account(
account_filter=account_filter
)
return raw_data


def _get_invoke_result_from_precommit_data(
precommit_data: PrecommitData) -> Tuple[List['TransactionResult'], bytes, dict, Optional[dict], bool]:
return (
precommit_data.block_result,
precommit_data.state_root_hash,
precommit_data.added_transactions,
precommit_data.next_preps,
precommit_data.is_shutdown,
)
7 changes: 5 additions & 2 deletions iconservice/precommit_data_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ def __init__(self,
rc_state_root_hash: Optional[bytes],
added_transactions: dict,
next_preps: Optional[dict],
prep_address_converter: 'PRepAddressConverter'):
prep_address_converter: 'PRepAddressConverter',
is_shutdown: bool):
"""
:param block_batch: changed states for a block
Expand Down Expand Up @@ -166,6 +167,7 @@ def __init__(self,
self.next_preps: Optional[dict] = next_preps

self.prep_address_converter: 'PRepAddressConverter' = prep_address_converter
self.is_shutdown = is_shutdown

# To prevent redundant precommit data logging
self.already_exists = False
Expand All @@ -185,7 +187,8 @@ def __str__(self):
f"state_root_hash: {bytes_to_hex(self.state_root_hash)}",
f"prev_block_generator: {self.prev_block_generator}",
f"added_transactions: {self.added_transactions}",
f"next_preps: {self.next_preps}"
f"next_preps: {self.next_preps}",
f"is_shutdown: {self.is_shutdown}",
]
return "\n".join(lines)

Expand Down
6 changes: 4 additions & 2 deletions tests/integrate_test/iiss/decentralized/test_decentralized.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,14 @@ def test_overlapped_block(self):
self.set_revision(Revision.IISS.value)
self.init_decentralized()

block, var1_1, var1_2, var1_3, var1_4 = self.debug_make_and_req_block(tx_list=[])
_, var2_1, var2_2, var2_3, var2_4 = self.debug_make_and_req_block(tx_list=[], block=block)
block, var1_1, var1_2, var1_3, var1_4, is_shutdown1 = self.debug_make_and_req_block(tx_list=[])
_, var2_1, var2_2, var2_3, var2_4, is_shutdown2 = self.debug_make_and_req_block(tx_list=[], block=block)
self.assertEqual(var1_1, var2_1)
self.assertEqual(var1_2, var2_2)
self.assertEqual(var1_3, var2_3)
self.assertEqual(var1_4, var2_4)
self.assertFalse(is_shutdown1)
self.assertFalse(is_shutdown2)

def test_estimate_step(self):
self.init_decentralized()
Expand Down
16 changes: 10 additions & 6 deletions tests/integrate_test/iiss/decentralized/test_decentralized2.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ def test_check_update_endpoint1(self):
tx: dict = self.create_set_prep_tx(from_=address,
set_data={"p2pEndpoint": new_p2p_endpoint})

_, _, _, _, next_preps = self.debug_make_and_req_block(tx_list=[tx])
_, _, _, _, next_preps, is_shutdown = self.debug_make_and_req_block(tx_list=[tx])
self.assertIsNone(next_preps)
self.assertFalse(is_shutdown)

self.set_revision(Revision.FIX_TOTAL_ELECTED_PREP_DELEGATED.value)
self.set_revision(Revision.REALTIME_P2P_ENDPOINT_UPDATE.value)
Expand All @@ -203,16 +204,18 @@ def test_check_update_endpoint1(self):
tx: dict = self.create_set_prep_tx(from_=address,
set_data={"p2pEndpoint": new_p2p_endpoint})

_, _, _, _, next_preps = self.debug_make_and_req_block(tx_list=[tx])
_, _, _, _, next_preps, is_shutdown = self.debug_make_and_req_block(tx_list=[tx])
self.assertEqual(new_p2p_endpoint, next_preps["preps"][0]["p2pEndpoint"])
self.assertFalse(is_shutdown)

# set prep with the same p2pEndpoint as the old one
tx: dict = self.create_set_prep_tx(from_=address,
set_data={"p2pEndpoint": old_p2p_endpoint})

# next_preps should not be modified
_, _, _, _, next_preps = self.debug_make_and_req_block(tx_list=[tx])
_, _, _, _, next_preps, is_shutdown = self.debug_make_and_req_block(tx_list=[tx])
assert next_preps is None
assert is_shutdown is False

def test_check_update_endpoint2(self):
self.update_governance()
Expand Down Expand Up @@ -250,8 +253,9 @@ def test_check_update_endpoint2(self):
tx_list.append(tx)

# To change the p2pEndpoints of sub P-Reps cannot affect next_preps
_, _, _, _, next_preps = self.debug_make_and_req_block(tx_list)
_, _, _, _, next_preps, is_shutdown = self.debug_make_and_req_block(tx_list)
assert next_preps is None
assert is_shutdown is False

self.process_confirm_block_tx(tx_list)

Expand All @@ -265,6 +269,6 @@ def test_check_update_endpoint2(self):

# Unregistered main P-Rep is replaced by the first sub P-Rep in descending order by delegated
tx: dict = self.create_unregister_prep_tx(self._accounts[0])
_, _, _, _, next_preps = self.debug_make_and_req_block(tx_list=[tx])

_, _, _, _, next_preps, is_shutdown = self.debug_make_and_req_block(tx_list=[tx])
assert is_shutdown is False
assert f"192.168.0.{start}:7100" == next_preps["preps"][0]["p2pEndpoint"]
Loading

0 comments on commit a4fc0c6

Please sign in to comment.