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

Commit

Permalink
IS-1215: Add debug_get_account api (#511)
Browse files Browse the repository at this point in the history
* fix acccess part in unstake_patcher
* support debug_get_account api in innerservice
  • Loading branch information
cow-hs authored Sep 2, 2020
1 parent 82fe331 commit 8c8a308
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 18 deletions.
10 changes: 9 additions & 1 deletion iconservice/base/type_converter_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ParamType(IntEnum):
ICX_GET_TOTAL_SUPPLY = 303
ICX_GET_SCORE_API = 304
ISE_GET_STATUS = 305
DEBUG_GET_ACCOUNT = 306

WRITE_PRECOMMIT = 400
# REMOVE_PRECOMMIT = 500
Expand Down Expand Up @@ -161,6 +162,7 @@ class ConstantKeys:
ICX_GET_TOTAL_SUPPLY = "icx_getTotalSupply"
ICX_GET_SCORE_API = "icx_getScoreApi"
ISE_GET_STATUS = "ise_getStatus"
DEBUG_GET_ACCOUNT = "debug_getAccount"

DEPOSIT_TERM = "term"
DEPOSIT_ID = "id"
Expand Down Expand Up @@ -304,6 +306,11 @@ class ConstantKeys:
ConstantKeys.FILTER: [ValueType.STRING]
}

type_convert_templates[ParamType.DEBUG_GET_ACCOUNT] = {
ConstantKeys.ADDRESS: ValueType.ADDRESS,
ConstantKeys.FILTER: ValueType.INT
}

type_convert_templates[ParamType.QUERY] = {
ConstantKeys.METHOD: ValueType.STRING,
ConstantKeys.PARAMS: {
Expand All @@ -313,7 +320,8 @@ class ConstantKeys:
ConstantKeys.ICX_GET_BALANCE: type_convert_templates[ParamType.ICX_GET_BALANCE],
ConstantKeys.ICX_GET_TOTAL_SUPPLY: type_convert_templates[ParamType.ICX_GET_TOTAL_SUPPLY],
ConstantKeys.ICX_GET_SCORE_API: type_convert_templates[ParamType.ICX_GET_SCORE_API],
ConstantKeys.ISE_GET_STATUS: type_convert_templates[ParamType.ISE_GET_STATUS]
ConstantKeys.ISE_GET_STATUS: type_convert_templates[ParamType.ISE_GET_STATUS],
ConstantKeys.DEBUG_GET_ACCOUNT: type_convert_templates[ParamType.DEBUG_GET_ACCOUNT],
}
}
}
Expand Down
1 change: 1 addition & 0 deletions iconservice/icon_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,4 @@ class RPCMethod:
ICX_CALL = 'icx_call'
ICX_SEND_TRANSACTION = 'icx_sendTransaction'
DEBUG_ESTIMATE_STEP = "debug_estimateStep"
DEBUG_GET_ACCOUNT = "debug_getAccount"
3 changes: 2 additions & 1 deletion iconservice/icon_inner_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
RPCMethod.ICX_GET_SCORE_API: THREAD_STATUS,
RPCMethod.ISE_GET_STATUS: THREAD_STATUS,
RPCMethod.ICX_CALL: THREAD_QUERY,
RPCMethod.DEBUG_ESTIMATE_STEP: THREAD_ESTIMATE
RPCMethod.DEBUG_ESTIMATE_STEP: THREAD_ESTIMATE,
RPCMethod.DEBUG_GET_ACCOUNT: THREAD_QUERY,
}

_TAG = "MQ"
Expand Down
31 changes: 28 additions & 3 deletions iconservice/icon_service_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from typing import TYPE_CHECKING, List, Optional, Tuple, Dict, Union, Any

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 @@ -64,7 +63,9 @@
from .icx import IcxEngine, IcxStorage
from .icx.issue import IssueEngine, IssueStorage
from .icx.issue.base_transaction_creator import BaseTransactionCreator
from .icx.unstake_patcher import UnstakePatcher, INVALID_EXPIRED_UNSTAKES_FILENAME
from .icx.storage import AccountPartFlag
from .icx.unstake_patcher import INVALID_EXPIRED_UNSTAKES_FILENAME
from .icx.unstake_patcher import UnstakePatcher
from .iiss import check_decentralization_condition
from .iiss.engine import Engine as IISSEngine
from .iiss.reward_calc import RewardCalcStorage
Expand Down Expand Up @@ -126,7 +127,8 @@ def __init__(self):
RPCMethod.ISE_GET_STATUS: self._handle_ise_get_status,
RPCMethod.ICX_CALL: self._handle_icx_call,
RPCMethod.DEBUG_ESTIMATE_STEP: self._handle_estimate_step,
RPCMethod.ICX_SEND_TRANSACTION: self._handle_icx_send_transaction
RPCMethod.ICX_SEND_TRANSACTION: self._handle_icx_send_transaction,
RPCMethod.DEBUG_GET_ACCOUNT: self._handle_debug_get_account
}

self._precommit_data_manager = PrecommitDataManager()
Expand Down Expand Up @@ -2127,3 +2129,26 @@ def _run_unstake_patcher(self, context: 'IconScoreContext'):
)

Logger.info(tag=_TAG, msg="_run_unstake_patcher() end")

@classmethod
def _handle_debug_get_account(
cls,
context: 'IconScoreContext',
params: dict
) -> dict:
"""
Handles get raw data of account in StateDB
:param context: context
:param params: parameters of account address and filter
:return: account raw data of stateDB
"""

address: 'Address' = params["address"]
account_filter: 'AccountPartFlag' = AccountPartFlag(params["filter"])
raw_data: dict = context.engine.icx.get_account_raw_data(
context=context,
address=address,
account_filter=account_filter
)
return raw_data
60 changes: 60 additions & 0 deletions iconservice/icx/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
from typing import TYPE_CHECKING

from .icx_account import Account
from .storage import AccountPartFlag
from ..base.ComponentBase import EngineBase
from ..base.address import Address
from ..base.exception import InvalidParamsException

if TYPE_CHECKING:
from ..iconscore.icon_score_context import IconScoreContext
from .coin_part import CoinPart
from .stake_part import StakePart
from .delegation_part import DelegationPart


class Engine(EngineBase):
Expand Down Expand Up @@ -97,3 +101,59 @@ def _transfer(self,
context.storage.icx.put_account(context, to_account)

return True

@classmethod
def get_account_raw_data(
cls,
context: 'IconScoreContext',
address: 'Address',
account_filter: 'AccountPartFlag'
) -> dict:
"""Get the balance of address
:param context:
:param address: account address
:param account_filter:
:return: raw data of account in stateDB
"""

ret = {}
if AccountPartFlag.COIN in account_filter:
part: 'CoinPart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.COIN,
address=address
)
ret["coin"] = {
"type": part.type.value,
"typeStr": str(part.type),
"flag": part.flags.value,
"flagStr": str(part.flags),
"balance": part.balance
}
if AccountPartFlag.STAKE in account_filter:
part: 'StakePart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.STAKE,
address=address
)
ret["stake"] = {
"stake": part.stake,
"unstake": part.unstake,
"unstakeBlockHeight": part.unstake_block_height,
"unstakesInfo": part.unstakes_info,
}
if AccountPartFlag.DELEGATION in account_filter:
part: 'DelegationPart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.DELEGATION,
address=address
)
ret["delegation"] = {
"totalDelegated": part.delegated_amount,
"delegations": [
{"address": delegation[0], "value": delegation[1]}
for delegation in part.delegations
],
}
return ret
28 changes: 19 additions & 9 deletions iconservice/icx/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,11 @@ def get_treasury_account(self, context: 'IconScoreContext') -> 'Account':
"""
return context.storage.icx.get_account(context, context.storage.icx.fee_treasury)

def _get_part(self, context: 'IconScoreContext',
part_class: Union[type(CoinPart), type(StakePart), type(DelegationPart)],
address: 'Address') -> Union['CoinPart', 'StakePart', 'DelegationPart']:
def _get_part(
self,
context: 'IconScoreContext',
part_class: Union[type(CoinPart), type(StakePart), type(DelegationPart)],
address: 'Address') -> Union['CoinPart', 'StakePart', 'DelegationPart']:
key: bytes = part_class.make_key(address)
value: bytes = self._db.get(context, key)

Expand Down Expand Up @@ -391,13 +393,21 @@ def put_total_supply(self,
value = value.to_bytes(DEFAULT_BYTE_SIZE, DATA_BYTE_ORDER)
self._db.put(context, self._TOTAL_SUPPLY_KEY, value)

def get_coin_part(self, context: 'IconScoreContext', address: 'Address') -> 'CoinPart':
part: 'CoinPart' = self._get_part(context, CoinPart, address)
part.set_complete(True)
return part
def get_part(
self,
context: 'IconScoreContext',
flag: 'AccountPartFlag',
address: 'Address'
) -> Union['CoinPart', 'StakePart', 'DelegationPart']:

if AccountPartFlag.COIN == flag:
part_class = CoinPart
elif AccountPartFlag.STAKE == flag:
part_class = StakePart
else:
part_class = DelegationPart

def get_stake_part(self, context: 'IconScoreContext', address: 'Address') -> 'StakePart':
part: 'StakePart' = self._get_part(context, StakePart, address)
part: Union['CoinPart', 'StakePart', 'DelegationPart'] = self._get_part(context, part_class, address)
part.set_complete(True)
return part

Expand Down
6 changes: 3 additions & 3 deletions iconservice/icx/unstake_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import TYPE_CHECKING, List, Dict, Any

from iconcommons.logger import Logger

from .storage import AccountPartFlag
from ..base.address import Address
from ..icx.coin_part import CoinPartFlag

Expand Down Expand Up @@ -126,8 +126,8 @@ def run(self, context: 'IconScoreContext'):

for target in self._targets:
address = target.address
coin_part = storage.get_coin_part(context, address)
stake_part = storage.get_stake_part(context, address)
coin_part = storage.get_part(context, AccountPartFlag.COIN, address)
stake_part = storage.get_part(context, AccountPartFlag.STAKE, address)

result: Result = self._check_removable(coin_part, stake_part, target)
if result == Result.FALSE:
Expand Down
122 changes: 122 additions & 0 deletions tests/integrate_test/iiss/decentralized/test_debug_get_acount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-

# Copyright 2018 ICON Foundation
#
# 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.

"""IconScoreEngine testcase
"""
from unittest.mock import Mock

from iconservice.base.address import SYSTEM_SCORE_ADDRESS
from iconservice.icon_constant import Revision, ICX_IN_LOOP
from iconservice.icx.storage import AccountPartFlag
from iconservice.iiss import IISSMethod
from iconservice.iiss.reward_calc.ipc.reward_calc_proxy import RewardCalcProxy
from tests.integrate_test.iiss.test_iiss_base import TestIISSBase


class TestIISS(TestIISSBase):
def test_debug_get_account_coin(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'coin': {
'type': 0,
'typeStr': 'GENERAL',
'flag': 0,
'flagStr': 'CoinPartFlag.NONE',
'balance': 0
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.COIN.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_stake(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'stake': {
'stake': 0,
'unstake': 0,
'unstakeBlockHeight': 0,
'unstakesInfo': []
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.STAKE.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_delegation(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'delegation': {
'delegations': [],
'totalDelegated': 0
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.DELEGATION.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_all(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'coin': {
'type': 0,
'typeStr': 'GENERAL',
'flag': 0,
'flagStr': 'CoinPartFlag.NONE',
'balance': 0
},
'stake': {
'stake': 0,
'unstake': 0,
'unstakeBlockHeight': 0,
'unstakesInfo': []
},
'delegation': {
'delegations': [],
'totalDelegated': 0
}
}
all_filter: AccountPartFlag = \
AccountPartFlag.COIN | \
AccountPartFlag.STAKE | \
AccountPartFlag.DELEGATION
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=all_filter.value
)
self.assertEqual(expected_ret, ret)
Loading

0 comments on commit 8c8a308

Please sign in to comment.